mirror of
				https://github.com/CorentinTh/it-tools.git
				synced 2025-11-03 21:43:21 +00:00 
			
		
		
		
	Compare commits
	
		
			15 Commits
		
	
	
		
			v2023.8.16
			...
			update-dep
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					facc0b5d9e | ||
| 
						 | 
					81bfe57cb8 | ||
| 
						 | 
					a9cd91ca9c | ||
| 
						 | 
					06c35472d3 | ||
| 
						 | 
					f3e14fc18f | ||
| 
						 | 
					2274766a8f | ||
| 
						 | 
					a346175d24 | ||
| 
						 | 
					6f93cba3da | ||
| 
						 | 
					76b2761d62 | ||
| 
						 | 
					6ff9a01cc8 | ||
| 
						 | 
					a2b9b157e5 | ||
| 
						 | 
					144f86e2dc | ||
| 
						 | 
					0f1f6590c5 | ||
| 
						 | 
					2bcb77a9f9 | ||
| 
						 | 
					c58d6e3423 | 
@@ -10,5 +10,12 @@ module.exports = {
 | 
			
		||||
    '@typescript-eslint/semi': ['error', 'always'],
 | 
			
		||||
    '@typescript-eslint/no-use-before-define': ['error', { allowNamedExports: true, functions: false }],
 | 
			
		||||
    'vue/no-empty-component-block': ['error'],
 | 
			
		||||
    'no-restricted-imports': ['error', {
 | 
			
		||||
      paths: [{
 | 
			
		||||
        name: '@vueuse/core',
 | 
			
		||||
        importNames: ['useClipboard'],
 | 
			
		||||
        message: 'Please use local useCopy from src/composable/copy.ts instead of useClipboard.',
 | 
			
		||||
      }],
 | 
			
		||||
    }],
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@@ -31,4 +31,6 @@ jobs:
 | 
			
		||||
        run: pnpm typecheck
 | 
			
		||||
 | 
			
		||||
      - name: Build the app
 | 
			
		||||
        env:
 | 
			
		||||
          NODE_OPTIONS: --max-old-space-size=4096
 | 
			
		||||
        run: pnpm build
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -2,6 +2,22 @@
 | 
			
		||||
 | 
			
		||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
 | 
			
		||||
 | 
			
		||||
## Version 2023.08.21-6f93cba
 | 
			
		||||
 | 
			
		||||
### Features
 | 
			
		||||
- **copy**: support legacy copy to clipboard for older browser (#581) (6f93cba)
 | 
			
		||||
- **new tool**: string obfuscator (#575) (c58d6e3)
 | 
			
		||||
 | 
			
		||||
### Bug fixes
 | 
			
		||||
- **deps**: update dependency sql-formatter to v12 (#520) (2bcb77a)
 | 
			
		||||
 | 
			
		||||
### Chores
 | 
			
		||||
- **deps**: switched to fucking typescript v5 (#501) (76b2761)
 | 
			
		||||
- **deps**: update dependency @antfu/eslint-config to ^0.40.0 (#552) (6ff9a01)
 | 
			
		||||
- **deps**: update dependency prettier to v3 (#564) (a2b9b15)
 | 
			
		||||
- **deps**: removed @typescript-eslint/parser (#563) (144f86e)
 | 
			
		||||
- **deps**: removed ts-pattern (#565) (0f1f659)
 | 
			
		||||
 | 
			
		||||
## Version 2023.08.16-9bd4ad4
 | 
			
		||||
 | 
			
		||||
### Features
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ docker run -d --name it-tools --restart unless-stopped -p 8080:80 ghcr.io/corent
 | 
			
		||||
 | 
			
		||||
**Other solutions:**
 | 
			
		||||
 | 
			
		||||
- [Cloudron](https://www.cloudron.io/store/tech.ittools.cloudron.html)
 | 
			
		||||
- [Tipi](https://www.runtipi.io/docs/apps-available)
 | 
			
		||||
- [Unraid](https://unraid.net/community/apps?q=it-tools)
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +35,7 @@ docker run -d --name it-tools --restart unless-stopped -p 8080:80 ghcr.io/corent
 | 
			
		||||
### Recommended IDE Setup
 | 
			
		||||
 | 
			
		||||
[VSCode](https://code.visualstudio.com/) with the following extensions:
 | 
			
		||||
 | 
			
		||||
- [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur)
 | 
			
		||||
- [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
 | 
			
		||||
- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
 | 
			
		||||
@@ -41,16 +43,13 @@ docker run -d --name it-tools --restart unless-stopped -p 8080:80 ghcr.io/corent
 | 
			
		||||
 | 
			
		||||
with the following settings:
 | 
			
		||||
 | 
			
		||||
```json5
 | 
			
		||||
```json
 | 
			
		||||
{
 | 
			
		||||
  "editor.formatOnSave": false,
 | 
			
		||||
  "editor.codeActionsOnSave": {
 | 
			
		||||
    "source.fixAll.eslint": true
 | 
			
		||||
  },
 | 
			
		||||
  "i18n-ally.localesPaths": [
 | 
			
		||||
    "locales",
 | 
			
		||||
    "src/tools/*/locales"
 | 
			
		||||
  ],
 | 
			
		||||
  "i18n-ally.localesPaths": ["locales", "src/tools/*/locales"],
 | 
			
		||||
  "i18n-ally.keystyle": "nested"
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -27,6 +27,7 @@ declare module '@vue/runtime-core' {
 | 
			
		||||
    'CButton.demo': typeof import('./src/ui/c-button/c-button.demo.vue')['default']
 | 
			
		||||
    CCard: typeof import('./src/ui/c-card/c-card.vue')['default']
 | 
			
		||||
    'CCard.demo': typeof import('./src/ui/c-card/c-card.demo.vue')['default']
 | 
			
		||||
    CDiffEditor: typeof import('./src/ui/c-diff-editor/c-diff-editor.vue')['default']
 | 
			
		||||
    ChmodCalculator: typeof import('./src/tools/chmod-calculator/chmod-calculator.vue')['default']
 | 
			
		||||
    Chronometer: typeof import('./src/tools/chronometer/chronometer.vue')['default']
 | 
			
		||||
    CInputText: typeof import('./src/ui/c-input-text/c-input-text.vue')['default']
 | 
			
		||||
@@ -45,7 +46,6 @@ declare module '@vue/runtime-core' {
 | 
			
		||||
    CSelect: typeof import('./src/ui/c-select/c-select.vue')['default']
 | 
			
		||||
    'CSelect.demo': typeof import('./src/ui/c-select/c-select.demo.vue')['default']
 | 
			
		||||
    DateTimeConverter: typeof import('./src/tools/date-time-converter/date-time-converter.vue')['default']
 | 
			
		||||
    'Demo.routes': typeof import('./src/ui/demo/demo.routes.vue')['default']
 | 
			
		||||
    'DemoHome.page': typeof import('./src/ui/demo/demo-home.page.vue')['default']
 | 
			
		||||
    DemoWrapper: typeof import('./src/ui/demo/demo-wrapper.vue')['default']
 | 
			
		||||
    DeviceInformation: typeof import('./src/tools/device-information/device-information.vue')['default']
 | 
			
		||||
@@ -69,11 +69,10 @@ declare module '@vue/runtime-core' {
 | 
			
		||||
    HtmlWysiwygEditor: typeof import('./src/tools/html-wysiwyg-editor/html-wysiwyg-editor.vue')['default']
 | 
			
		||||
    HttpStatusCodes: typeof import('./src/tools/http-status-codes/http-status-codes.vue')['default']
 | 
			
		||||
    'IconMdi:brushVariant': typeof import('~icons/mdi/brush-variant')['default']
 | 
			
		||||
    'IconMdi:contentCopy': typeof import('~icons/mdi/content-copy')['default']
 | 
			
		||||
    'IconMdi:kettleSteamOutline': typeof import('~icons/mdi/kettle-steam-outline')['default']
 | 
			
		||||
    IconMdiArrowRightBottom: typeof import('~icons/mdi/arrow-right-bottom')['default']
 | 
			
		||||
    IconMdiCamera: typeof import('~icons/mdi/camera')['default']
 | 
			
		||||
    IconMdiCameraOutline: typeof import('~icons/mdi/camera-outline')['default']
 | 
			
		||||
    IconMdiCameraVideoOff: typeof import('~icons/mdi/camera-video-off')['default']
 | 
			
		||||
    IconMdiChevronDown: typeof import('~icons/mdi/chevron-down')['default']
 | 
			
		||||
    IconMdiChevronRight: typeof import('~icons/mdi/chevron-right')['default']
 | 
			
		||||
    IconMdiClose: typeof import('~icons/mdi/close')['default']
 | 
			
		||||
@@ -82,14 +81,11 @@ declare module '@vue/runtime-core' {
 | 
			
		||||
    IconMdiDownload: typeof import('~icons/mdi/download')['default']
 | 
			
		||||
    IconMdiEye: typeof import('~icons/mdi/eye')['default']
 | 
			
		||||
    IconMdiEyeOff: typeof import('~icons/mdi/eye-off')['default']
 | 
			
		||||
    IconMdiMagnify: typeof import('~icons/mdi/magnify')['default']
 | 
			
		||||
    IconMdiPause: typeof import('~icons/mdi/pause')['default']
 | 
			
		||||
    IconMdiPlay: typeof import('~icons/mdi/play')['default']
 | 
			
		||||
    IconMdiRecord: typeof import('~icons/mdi/record')['default']
 | 
			
		||||
    IconMdiRefresh: typeof import('~icons/mdi/refresh')['default']
 | 
			
		||||
    IconMdiSearch: typeof import('~icons/mdi/search')['default']
 | 
			
		||||
    IconMdiSearchRound: typeof import('~icons/mdi/search-round')['default']
 | 
			
		||||
    IconMdiTea: typeof import('~icons/mdi/tea')['default']
 | 
			
		||||
    IconMdiVideo: typeof import('~icons/mdi/video')['default']
 | 
			
		||||
    InputCopyable: typeof import('./src/components/InputCopyable.vue')['default']
 | 
			
		||||
    IntegerBaseConverter: typeof import('./src/tools/integer-base-converter/integer-base-converter.vue')['default']
 | 
			
		||||
@@ -135,7 +131,6 @@ declare module '@vue/runtime-core' {
 | 
			
		||||
    NH3: typeof import('naive-ui')['NH3']
 | 
			
		||||
    NIcon: typeof import('naive-ui')['NIcon']
 | 
			
		||||
    NImage: typeof import('naive-ui')['NImage']
 | 
			
		||||
    NInput: typeof import('naive-ui')['NInput']
 | 
			
		||||
    NInputGroup: typeof import('naive-ui')['NInputGroup']
 | 
			
		||||
    NInputGroupLabel: typeof import('naive-ui')['NInputGroupLabel']
 | 
			
		||||
    NInputNumber: typeof import('naive-ui')['NInputNumber']
 | 
			
		||||
@@ -146,13 +141,11 @@ declare module '@vue/runtime-core' {
 | 
			
		||||
    NPageHeader: typeof import('naive-ui')['NPageHeader']
 | 
			
		||||
    NProgress: typeof import('naive-ui')['NProgress']
 | 
			
		||||
    NScrollbar: typeof import('naive-ui')['NScrollbar']
 | 
			
		||||
    NSelect: typeof import('naive-ui')['NSelect']
 | 
			
		||||
    NSlider: typeof import('naive-ui')['NSlider']
 | 
			
		||||
    NStatistic: typeof import('naive-ui')['NStatistic']
 | 
			
		||||
    NSwitch: typeof import('naive-ui')['NSwitch']
 | 
			
		||||
    NTable: typeof import('naive-ui')['NTable']
 | 
			
		||||
    NTag: typeof import('naive-ui')['NTag']
 | 
			
		||||
    NText: typeof import('naive-ui')['NText']
 | 
			
		||||
    NTooltip: typeof import('naive-ui')['NTooltip']
 | 
			
		||||
    NUpload: typeof import('naive-ui')['NUpload']
 | 
			
		||||
    NUploadDragger: typeof import('naive-ui')['NUploadDragger']
 | 
			
		||||
@@ -170,9 +163,11 @@ declare module '@vue/runtime-core' {
 | 
			
		||||
    SlugifyString: typeof import('./src/tools/slugify-string/slugify-string.vue')['default']
 | 
			
		||||
    SpanCopyable: typeof import('./src/components/SpanCopyable.vue')['default']
 | 
			
		||||
    SqlPrettify: typeof import('./src/tools/sql-prettify/sql-prettify.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']
 | 
			
		||||
    TemperatureConverter: typeof import('./src/tools/temperature-converter/temperature-converter.vue')['default']
 | 
			
		||||
    TextareaCopyable: typeof import('./src/components/TextareaCopyable.vue')['default']
 | 
			
		||||
    TextDiff: typeof import('./src/tools/text-diff/text-diff.vue')['default']
 | 
			
		||||
    TextStatistics: typeof import('./src/tools/text-statistics/text-statistics.vue')['default']
 | 
			
		||||
    TextToNatoAlphabet: typeof import('./src/tools/text-to-nato-alphabet/text-to-nato-alphabet.vue')['default']
 | 
			
		||||
    TokenDisplay: typeof import('./src/tools/otp-code-generator-and-validator/token-display.vue')['default']
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										117
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								package.json
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "it-tools",
 | 
			
		||||
  "version": "2023.8.16-9bd4ad4",
 | 
			
		||||
  "version": "2023.8.21-6f93cba",
 | 
			
		||||
  "description": "Collection of handy online tools for developers, with great UX. ",
 | 
			
		||||
  "keywords": [
 | 
			
		||||
    "productivity",
 | 
			
		||||
@@ -35,100 +35,99 @@
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@it-tools/bip39": "^0.0.4",
 | 
			
		||||
    "@it-tools/oggen": "^1.3.0",
 | 
			
		||||
    "@sindresorhus/slugify": "^2.2.0",
 | 
			
		||||
    "@tiptap/pm": "^2.0.3",
 | 
			
		||||
    "@tiptap/starter-kit": "^2.0.3",
 | 
			
		||||
    "@tiptap/vue-3": "^2.0.3",
 | 
			
		||||
    "@sindresorhus/slugify": "^2.2.1",
 | 
			
		||||
    "@tiptap/pm": "^2.1.7",
 | 
			
		||||
    "@tiptap/starter-kit": "^2.1.7",
 | 
			
		||||
    "@tiptap/vue-3": "^2.1.7",
 | 
			
		||||
    "@vicons/material": "^0.12.0",
 | 
			
		||||
    "@vicons/tabler": "^0.12.0",
 | 
			
		||||
    "@vueuse/core": "^10.1.2",
 | 
			
		||||
    "@vueuse/head": "^1.0.0",
 | 
			
		||||
    "@vueuse/router": "^10.0.0",
 | 
			
		||||
    "@vueuse/core": "^10.4.0",
 | 
			
		||||
    "@vueuse/head": "^1.3.1",
 | 
			
		||||
    "@vueuse/router": "^10.4.0",
 | 
			
		||||
    "bcryptjs": "^2.4.3",
 | 
			
		||||
    "change-case": "^4.1.2",
 | 
			
		||||
    "colord": "^2.9.3",
 | 
			
		||||
    "composerize-ts": "^0.6.2",
 | 
			
		||||
    "country-code-lookup": "^0.1.0",
 | 
			
		||||
    "cron-validator": "^1.3.1",
 | 
			
		||||
    "cronstrue": "^2.26.0",
 | 
			
		||||
    "cronstrue": "^2.31.0",
 | 
			
		||||
    "crypto-js": "^4.1.1",
 | 
			
		||||
    "date-fns": "^2.29.3",
 | 
			
		||||
    "date-fns": "^2.30.0",
 | 
			
		||||
    "emojilib": "^3.0.10",
 | 
			
		||||
    "figue": "^1.2.0",
 | 
			
		||||
    "fuse.js": "^6.6.2",
 | 
			
		||||
    "highlight.js": "^11.7.0",
 | 
			
		||||
    "highlight.js": "^11.8.0",
 | 
			
		||||
    "iarna-toml-esm": "^3.0.5",
 | 
			
		||||
    "json5": "^2.2.3",
 | 
			
		||||
    "jwt-decode": "^3.1.2",
 | 
			
		||||
    "libphonenumber-js": "^1.10.28",
 | 
			
		||||
    "libphonenumber-js": "^1.10.41",
 | 
			
		||||
    "lodash": "^4.17.21",
 | 
			
		||||
    "mathjs": "^11.0.0",
 | 
			
		||||
    "mathjs": "^11.10.0",
 | 
			
		||||
    "mime-types": "^2.1.35",
 | 
			
		||||
    "naive-ui": "^2.34.3",
 | 
			
		||||
    "monaco-editor": "^0.41.0",
 | 
			
		||||
    "naive-ui": "^2.34.4",
 | 
			
		||||
    "netmask": "^2.0.2",
 | 
			
		||||
    "node-forge": "^1.3.1",
 | 
			
		||||
    "oui": "^12.0.52",
 | 
			
		||||
    "pinia": "^2.0.34",
 | 
			
		||||
    "oui": "^12.0.71",
 | 
			
		||||
    "pinia": "^2.1.6",
 | 
			
		||||
    "plausible-tracker": "^0.3.8",
 | 
			
		||||
    "qrcode": "^1.5.1",
 | 
			
		||||
    "qrcode": "^1.5.3",
 | 
			
		||||
    "randombytes": "^2.1.0",
 | 
			
		||||
    "sql-formatter": "^8.2.0",
 | 
			
		||||
    "ts-pattern": "^4.2.2",
 | 
			
		||||
    "sql-formatter": "^12.2.4",
 | 
			
		||||
    "ua-parser-js": "^1.0.35",
 | 
			
		||||
    "unicode-emoji-json": "^0.4.0",
 | 
			
		||||
    "unplugin-auto-import": "^0.16.4",
 | 
			
		||||
    "unplugin-auto-import": "^0.16.6",
 | 
			
		||||
    "uuid": "^9.0.0",
 | 
			
		||||
    "vue": "^3.3.4",
 | 
			
		||||
    "vue-i18n": "^9.2.2",
 | 
			
		||||
    "vue-router": "^4.1.6",
 | 
			
		||||
    "vue-tsc": "^1.8.1",
 | 
			
		||||
    "xml-formatter": "^3.3.2",
 | 
			
		||||
    "yaml": "^2.2.1"
 | 
			
		||||
    "vue-router": "^4.2.4",
 | 
			
		||||
    "vue-tsc": "^1.8.8",
 | 
			
		||||
    "xml-formatter": "^3.5.0",
 | 
			
		||||
    "yaml": "^2.3.1"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@antfu/eslint-config": "^0.39.3",
 | 
			
		||||
    "@iconify-json/mdi": "^1.1.50",
 | 
			
		||||
    "@intlify/unplugin-vue-i18n": "^0.12.0",
 | 
			
		||||
    "@playwright/test": "^1.32.3",
 | 
			
		||||
    "@rushstack/eslint-patch": "^1.2.0",
 | 
			
		||||
    "@antfu/eslint-config": "^0.41.0",
 | 
			
		||||
    "@iconify-json/mdi": "^1.1.54",
 | 
			
		||||
    "@intlify/unplugin-vue-i18n": "^0.12.3",
 | 
			
		||||
    "@playwright/test": "^1.37.1",
 | 
			
		||||
    "@rushstack/eslint-patch": "^1.3.3",
 | 
			
		||||
    "@tsconfig/node18": "^18.2.1",
 | 
			
		||||
    "@types/bcryptjs": "^2.4.2",
 | 
			
		||||
    "@types/crypto-js": "^4.1.1",
 | 
			
		||||
    "@types/jsdom": "^21.0.0",
 | 
			
		||||
    "@types/lodash": "^4.14.192",
 | 
			
		||||
    "@types/jsdom": "^21.1.2",
 | 
			
		||||
    "@types/lodash": "^4.14.197",
 | 
			
		||||
    "@types/mime-types": "^2.1.1",
 | 
			
		||||
    "@types/netmask": "^2.0.0",
 | 
			
		||||
    "@types/node": "^18.0.0",
 | 
			
		||||
    "@types/node-forge": "^1.3.2",
 | 
			
		||||
    "@types/prettier": "^2.7.2",
 | 
			
		||||
    "@types/qrcode": "^1.5.0",
 | 
			
		||||
    "@types/netmask": "^2.0.2",
 | 
			
		||||
    "@types/node": "^18.17.11",
 | 
			
		||||
    "@types/node-forge": "^1.3.4",
 | 
			
		||||
    "@types/qrcode": "^1.5.1",
 | 
			
		||||
    "@types/randombytes": "^2.0.0",
 | 
			
		||||
    "@types/ua-parser-js": "^0.7.36",
 | 
			
		||||
    "@types/uuid": "^9.0.0",
 | 
			
		||||
    "@typescript-eslint/parser": "^5.58.0",
 | 
			
		||||
    "@unocss/eslint-config": "^0.55.0",
 | 
			
		||||
    "@vitejs/plugin-vue": "^4.0.0",
 | 
			
		||||
    "@vitejs/plugin-vue-jsx": "^3.0.0",
 | 
			
		||||
    "@vue/compiler-sfc": "^3.2.47",
 | 
			
		||||
    "@types/uuid": "^9.0.2",
 | 
			
		||||
    "@unocss/eslint-config": "^0.55.3",
 | 
			
		||||
    "@vitejs/plugin-vue": "^4.3.3",
 | 
			
		||||
    "@vitejs/plugin-vue-jsx": "^3.0.2",
 | 
			
		||||
    "@vue/compiler-sfc": "^3.3.4",
 | 
			
		||||
    "@vue/runtime-dom": "^3.3.4",
 | 
			
		||||
    "@vue/test-utils": "^2.3.2",
 | 
			
		||||
    "@vue/tsconfig": "^0.1.3",
 | 
			
		||||
    "c8": "^8.0.0",
 | 
			
		||||
    "consola": "^3.0.2",
 | 
			
		||||
    "eslint": "^8.38.0",
 | 
			
		||||
    "jsdom": "^22.0.0",
 | 
			
		||||
    "less": "^4.1.3",
 | 
			
		||||
    "prettier": "^2.8.7",
 | 
			
		||||
    "typescript": "~4.9.0",
 | 
			
		||||
    "unocss": "^0.55.0",
 | 
			
		||||
    "@vue/test-utils": "^2.4.1",
 | 
			
		||||
    "@vue/tsconfig": "^0.4.0",
 | 
			
		||||
    "c8": "^8.0.1",
 | 
			
		||||
    "consola": "^3.2.3",
 | 
			
		||||
    "eslint": "^8.48.0",
 | 
			
		||||
    "jsdom": "^22.1.0",
 | 
			
		||||
    "less": "^4.2.0",
 | 
			
		||||
    "prettier": "^3.0.2",
 | 
			
		||||
    "typescript": "~5.2.2",
 | 
			
		||||
    "unocss": "^0.55.3",
 | 
			
		||||
    "unocss-preset-scrollbar": "^0.2.1",
 | 
			
		||||
    "unplugin-icons": "^0.16.1",
 | 
			
		||||
    "unplugin-vue-components": "^0.25.0",
 | 
			
		||||
    "vite": "^4.0.0",
 | 
			
		||||
    "vite-plugin-pwa": "^0.16.0",
 | 
			
		||||
    "vite-plugin-vue-markdown": "^0.23.5",
 | 
			
		||||
    "unplugin-icons": "^0.16.5",
 | 
			
		||||
    "unplugin-vue-components": "^0.25.1",
 | 
			
		||||
    "vite": "^4.4.9",
 | 
			
		||||
    "vite-plugin-pwa": "^0.16.4",
 | 
			
		||||
    "vite-plugin-vue-markdown": "^0.23.8",
 | 
			
		||||
    "vite-svg-loader": "^4.0.0",
 | 
			
		||||
    "vitest": "^0.34.0",
 | 
			
		||||
    "vitest": "^0.34.3",
 | 
			
		||||
    "workbox-window": "^7.0.0",
 | 
			
		||||
    "zx": "^7.2.1"
 | 
			
		||||
    "zx": "^7.2.3"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4557
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4557
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,22 +1,13 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { useClipboard, useVModel } from '@vueuse/core';
 | 
			
		||||
import { useVModel } from '@vueuse/core';
 | 
			
		||||
import { useCopy } from '@/composable/copy';
 | 
			
		||||
 | 
			
		||||
const props = defineProps<{ value: string }>();
 | 
			
		||||
const emit = defineEmits(['update:value']);
 | 
			
		||||
 | 
			
		||||
const value = useVModel(props, 'value', emit);
 | 
			
		||||
const tooltipText = ref('Copy to clipboard');
 | 
			
		||||
 | 
			
		||||
const { copy } = useClipboard({ source: value });
 | 
			
		||||
 | 
			
		||||
function onCopyClicked() {
 | 
			
		||||
  copy();
 | 
			
		||||
  tooltipText.value = 'Copied!';
 | 
			
		||||
 | 
			
		||||
  setTimeout(() => {
 | 
			
		||||
    tooltipText.value = 'Copy to clipboard';
 | 
			
		||||
  }, 2000);
 | 
			
		||||
}
 | 
			
		||||
const { copy, isJustCopied } = useCopy({ source: value, createToast: false });
 | 
			
		||||
const tooltipText = computed(() => isJustCopied.value ? 'Copied!' : 'Copy to clipboard');
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
@@ -24,7 +15,7 @@ function onCopyClicked() {
 | 
			
		||||
    <template #suffix>
 | 
			
		||||
      <n-tooltip trigger="hover">
 | 
			
		||||
        <template #trigger>
 | 
			
		||||
          <c-button circle variant="text" size="small" @click="onCopyClicked">
 | 
			
		||||
          <c-button circle variant="text" size="small" @click="copy()">
 | 
			
		||||
            <icon-mdi-content-copy />
 | 
			
		||||
          </c-button>
 | 
			
		||||
        </template>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,26 +1,19 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { useClipboard } from '@vueuse/core';
 | 
			
		||||
import { useCopy } from '@/composable/copy';
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(defineProps<{ value?: string }>(), { value: '' });
 | 
			
		||||
const { value } = toRefs(props);
 | 
			
		||||
 | 
			
		||||
const initialText = 'Copy to clipboard';
 | 
			
		||||
const tooltipText = ref(initialText);
 | 
			
		||||
 | 
			
		||||
const { copy } = useClipboard({ source: value });
 | 
			
		||||
 | 
			
		||||
function handleClick() {
 | 
			
		||||
  copy();
 | 
			
		||||
  tooltipText.value = 'Copied!';
 | 
			
		||||
 | 
			
		||||
  setTimeout(() => (tooltipText.value = initialText), 1000);
 | 
			
		||||
}
 | 
			
		||||
const { copy, isJustCopied } = useCopy({ source: value, createToast: false });
 | 
			
		||||
const tooltipText = computed(() => isJustCopied.value ? 'Copied!' : initialText);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <n-tooltip trigger="hover">
 | 
			
		||||
    <template #trigger>
 | 
			
		||||
      <span class="value" @click="handleClick">{{ value }}</span>
 | 
			
		||||
      <span class="value" @click="copy()">{{ value }}</span>
 | 
			
		||||
    </template>
 | 
			
		||||
    {{ tooltipText }}
 | 
			
		||||
  </n-tooltip>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,13 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { Copy } from '@vicons/tabler';
 | 
			
		||||
import { useClipboard, useElementSize } from '@vueuse/core';
 | 
			
		||||
import { useElementSize } from '@vueuse/core';
 | 
			
		||||
import hljs from 'highlight.js/lib/core';
 | 
			
		||||
import jsonHljs from 'highlight.js/lib/languages/json';
 | 
			
		||||
import sqlHljs from 'highlight.js/lib/languages/sql';
 | 
			
		||||
import xmlHljs from 'highlight.js/lib/languages/xml';
 | 
			
		||||
import yamlHljs from 'highlight.js/lib/languages/yaml';
 | 
			
		||||
import iniHljs from 'highlight.js/lib/languages/ini';
 | 
			
		||||
import { useCopy } from '@/composable/copy';
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(
 | 
			
		||||
  defineProps<{
 | 
			
		||||
@@ -33,17 +34,8 @@ hljs.registerLanguage('toml', iniHljs);
 | 
			
		||||
const { value, language, followHeightOf, copyPlacement, copyMessage } = toRefs(props);
 | 
			
		||||
const { height } = followHeightOf.value ? useElementSize(followHeightOf) : { height: ref(null) };
 | 
			
		||||
 | 
			
		||||
const { copy } = useClipboard({ source: value });
 | 
			
		||||
const tooltipText = ref(copyMessage.value);
 | 
			
		||||
 | 
			
		||||
function onCopyClicked() {
 | 
			
		||||
  copy();
 | 
			
		||||
  tooltipText.value = 'Copied !';
 | 
			
		||||
 | 
			
		||||
  setTimeout(() => {
 | 
			
		||||
    tooltipText.value = copyMessage.value;
 | 
			
		||||
  }, 2000);
 | 
			
		||||
}
 | 
			
		||||
const { copy, isJustCopied } = useCopy({ source: value, createToast: false });
 | 
			
		||||
const tooltipText = computed(() => isJustCopied.value ? 'Copied!' : copyMessage.value);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
@@ -61,7 +53,7 @@ function onCopyClicked() {
 | 
			
		||||
      <n-tooltip v-if="value" trigger="hover">
 | 
			
		||||
        <template #trigger>
 | 
			
		||||
          <div class="copy-button" :class="[copyPlacement]">
 | 
			
		||||
            <c-button circle important:h-10 important:w-10 @click="onCopyClicked">
 | 
			
		||||
            <c-button circle important:h-10 important:w-10 @click="copy()">
 | 
			
		||||
              <n-icon size="22" :component="Copy" />
 | 
			
		||||
            </c-button>
 | 
			
		||||
          </div>
 | 
			
		||||
@@ -70,7 +62,7 @@ function onCopyClicked() {
 | 
			
		||||
      </n-tooltip>
 | 
			
		||||
    </c-card>
 | 
			
		||||
    <div v-if="copyPlacement === 'outside'" mt-4 flex justify-center>
 | 
			
		||||
      <c-button @click="onCopyClicked">
 | 
			
		||||
      <c-button @click="copy()">
 | 
			
		||||
        {{ tooltipText }}
 | 
			
		||||
      </c-button>
 | 
			
		||||
    </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,19 @@
 | 
			
		||||
import { type MaybeRef, get, useClipboard } from '@vueuse/core';
 | 
			
		||||
// eslint-disable-next-line no-restricted-imports
 | 
			
		||||
import { useClipboard } from '@vueuse/core';
 | 
			
		||||
import { useMessage } from 'naive-ui';
 | 
			
		||||
import type { MaybeRefOrGetter } from 'vue';
 | 
			
		||||
 | 
			
		||||
export function useCopy({ source, text = 'Copied to the clipboard', createToast = true }: { source?: MaybeRefOrGetter<string>; text?: string; createToast?: boolean } = {}) {
 | 
			
		||||
  const { copy, copied, ...rest } = useClipboard({
 | 
			
		||||
    source,
 | 
			
		||||
    legacy: true,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
export function useCopy({ source, text = 'Copied to the clipboard' }: { source?: MaybeRef<unknown>; text?: string } = {}) {
 | 
			
		||||
  const { copy } = useClipboard(source ? { source: computed(() => String(get(source))) } : {});
 | 
			
		||||
  const message = useMessage();
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    ...rest,
 | 
			
		||||
    isJustCopied: copied,
 | 
			
		||||
    async copy(content?: string, { notificationMessage }: { notificationMessage?: string } = {}) {
 | 
			
		||||
      if (source) {
 | 
			
		||||
        await copy();
 | 
			
		||||
@@ -14,7 +22,9 @@ export function useCopy({ source, text = 'Copied to the clipboard' }: { source?:
 | 
			
		||||
        await copy(content);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (createToast) {
 | 
			
		||||
        message.success(notificationMessage ?? text);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								src/shims.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								src/shims.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -1,21 +1,35 @@
 | 
			
		||||
declare module '*.vue' {
 | 
			
		||||
  import type { ComponentOptions, ComponentOptions } from 'vue';
 | 
			
		||||
  import type {  ComponentOptions } from 'vue';
 | 
			
		||||
  const Component: ComponentOptions;
 | 
			
		||||
  export default Component;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
declare module '*.md' {
 | 
			
		||||
  import type {  ComponentOptions } from 'vue';
 | 
			
		||||
  const Component: ComponentOptions;
 | 
			
		||||
  export default Component;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
declare module '~icons/*' {
 | 
			
		||||
  import { FunctionalComponent, SVGAttributes } from 'vue';
 | 
			
		||||
  const component: FunctionalComponent<SVGAttributes>;
 | 
			
		||||
  export default component;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
declare module 'iarna-toml-esm' {
 | 
			
		||||
  export const parse: (toml: string) => any;
 | 
			
		||||
  export const stringify: (obj: any) => string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
declare module 'emojilib' {
 | 
			
		||||
  const lib: Record<string, string[]>;
 | 
			
		||||
  export default lib;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
declare module 'unicode-emoji-json' {
 | 
			
		||||
  const emoji: Record<string, {
 | 
			
		||||
    name: string;
 | 
			
		||||
    slug: string;
 | 
			
		||||
    group: string;
 | 
			
		||||
    emoji_version: string;
 | 
			
		||||
    unicode_version: string;
 | 
			
		||||
    skin_tone_support: boolean;
 | 
			
		||||
    skin_tone_support_unicode_version: string;
 | 
			
		||||
  }>;
 | 
			
		||||
  
 | 
			
		||||
  export default emoji;
 | 
			
		||||
}
 | 
			
		||||
@@ -18,7 +18,7 @@ function computeVariance({ data }: { data: number[] }) {
 | 
			
		||||
  return computeAverage({ data: squaredDiffs });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function arrayToMarkdownTable({ data, headerMap = {} }: { data: unknown[]; headerMap?: Record<string, string> }) {
 | 
			
		||||
function arrayToMarkdownTable({ data, headerMap = {} }: { data: Record<string, unknown>[]; headerMap?: Record<string, string> }) {
 | 
			
		||||
  if (!Array.isArray(data) || data.length === 0) {
 | 
			
		||||
    return '';
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,11 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { Plus, Trash } from '@vicons/tabler';
 | 
			
		||||
import { useClipboard, useStorage } from '@vueuse/core';
 | 
			
		||||
import { useStorage } from '@vueuse/core';
 | 
			
		||||
import _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { arrayToMarkdownTable, computeAverage, computeVariance } from './benchmark-builder.models';
 | 
			
		||||
import DynamicValues from './dynamic-values.vue';
 | 
			
		||||
import { useCopy } from '@/composable/copy';
 | 
			
		||||
 | 
			
		||||
const suites = useStorage('benchmark-builder:suites', [
 | 
			
		||||
  { title: 'Suite 1', data: [5, 10] },
 | 
			
		||||
@@ -47,7 +48,7 @@ const results = computed(() => {
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { copy } = useClipboard();
 | 
			
		||||
const { copy } = useCopy({ createToast: false });
 | 
			
		||||
 | 
			
		||||
const header = {
 | 
			
		||||
  title: 'Suite',
 | 
			
		||||
 
 | 
			
		||||
@@ -92,7 +92,7 @@ const inputLabelAlignmentConfig = {
 | 
			
		||||
      v-bind="inputLabelAlignmentConfig"
 | 
			
		||||
    />
 | 
			
		||||
 | 
			
		||||
    <div divider my-16px />
 | 
			
		||||
    <div my-16px divider />
 | 
			
		||||
 | 
			
		||||
    <InputCopyable
 | 
			
		||||
      v-for="format in formats"
 | 
			
		||||
 
 | 
			
		||||
@@ -82,7 +82,7 @@ const formats: DateFormat[] = [
 | 
			
		||||
  {
 | 
			
		||||
    name: 'Mongo ObjectID',
 | 
			
		||||
    fromDate: date => `${Math.floor(date.getTime() / 1000).toString(16)}0000000000000000`,
 | 
			
		||||
    toDate: objectId => new Date(parseInt(objectId.substring(0, 8), 16) * 1000),
 | 
			
		||||
    toDate: objectId => new Date(Number.parseInt(objectId.substring(0, 8), 16) * 1000),
 | 
			
		||||
    formatMatcher: date => isMongoObjectId(date),
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ const { copy } = useCopy();
 | 
			
		||||
        Unicode:  <span border="1px solid current op-30" b-rd-xl px-12px py-4px>{{ emojiInfo.unicode }}</span>
 | 
			
		||||
      </div> -->
 | 
			
		||||
 | 
			
		||||
      <div flex gap-2 font-mono text-xs op-70>
 | 
			
		||||
      <div flex gap-2 text-xs font-mono op-70>
 | 
			
		||||
        <span cursor-pointer transition hover:text-primary @click="copy(emojiInfo.codePoints, { notificationMessage: `Code points '${emojiInfo.codePoints}' copied to the clipboard` })">
 | 
			
		||||
          {{ emojiInfo.codePoints }}
 | 
			
		||||
        </span>
 | 
			
		||||
 
 | 
			
		||||
@@ -5,4 +5,4 @@ export type EmojiInfo = {
 | 
			
		||||
  emoji: string
 | 
			
		||||
  codePoints: string | undefined
 | 
			
		||||
  unicode: string
 | 
			
		||||
} & typeof emojiUnicodeData['\uD83E\uDD10'];
 | 
			
		||||
} & typeof emojiUnicodeData[string];
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,6 @@ export function convertHexToBin(hex: string) {
 | 
			
		||||
  return hex
 | 
			
		||||
    .trim()
 | 
			
		||||
    .split('')
 | 
			
		||||
    .map(byte => parseInt(byte, 16).toString(2).padStart(4, '0'))
 | 
			
		||||
    .map(byte => Number.parseInt(byte, 16).toString(2).padStart(4, '0'))
 | 
			
		||||
    .join('');
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,16 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { format } from 'prettier';
 | 
			
		||||
import htmlParser from 'prettier/parser-html';
 | 
			
		||||
import htmlParser from 'prettier/plugins/html';
 | 
			
		||||
import { useStorage } from '@vueuse/core';
 | 
			
		||||
import Editor from './editor/editor.vue';
 | 
			
		||||
import TextareaCopyable from '@/components/TextareaCopyable.vue';
 | 
			
		||||
 | 
			
		||||
const html = useStorage('html-wysiwyg-editor--html', '<h1>Hey!</h1><p>Welcome to this html wysiwyg editor</p>');
 | 
			
		||||
 | 
			
		||||
const formattedHtml = asyncComputed(() => format(html.value, { parser: 'html', plugins: [htmlParser] }), '');
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <Editor v-model:html="html" />
 | 
			
		||||
  <TextareaCopyable :value="format(html, { parser: 'html', plugins: [htmlParser] })" language="html" />
 | 
			
		||||
  <TextareaCopyable :value="formattedHtml" language="html" />
 | 
			
		||||
</template>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
import { tool as base64FileConverter } from './base64-file-converter';
 | 
			
		||||
import { tool as base64StringConverter } from './base64-string-converter';
 | 
			
		||||
import { tool as basicAuthGenerator } from './basic-auth-generator';
 | 
			
		||||
import { tool as stringObfuscator } from './string-obfuscator';
 | 
			
		||||
import { tool as textDiff } from './text-diff';
 | 
			
		||||
import { tool as emojiPicker } from './emoji-picker';
 | 
			
		||||
import { tool as passwordStrengthAnalyser } from './password-strength-analyser';
 | 
			
		||||
import { tool as yamlToToml } from './yaml-to-toml';
 | 
			
		||||
@@ -145,7 +147,7 @@ export const toolsByCategory: ToolCategory[] = [
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'Text',
 | 
			
		||||
    components: [loremIpsumGenerator, textStatistics, emojiPicker],
 | 
			
		||||
    components: [loremIpsumGenerator, textStatistics, emojiPicker, stringObfuscator, textDiff],
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    name: 'Data',
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ function ipv4ToIpv6({ ip, prefix = '0000:0000:0000:0000:0000:ffff:' }: { ip: str
 | 
			
		||||
    + _.chain(ip)
 | 
			
		||||
      .trim()
 | 
			
		||||
      .split('.')
 | 
			
		||||
      .map(part => parseInt(part).toString(16).padStart(2, '0'))
 | 
			
		||||
      .map(part => Number.parseInt(part).toString(16).padStart(2, '0'))
 | 
			
		||||
      .chunk(2)
 | 
			
		||||
      .map(blocks => blocks.join(''))
 | 
			
		||||
      .join(':')
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ function getRangesize(start: string, end: string) {
 | 
			
		||||
    return -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return 1 + parseInt(end, 2) - parseInt(start, 2);
 | 
			
		||||
  return 1 + Number.parseInt(end, 2) - Number.parseInt(start, 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getCidr(start: string, end: string) {
 | 
			
		||||
@@ -55,8 +55,8 @@ function calculateCidr({ startIp, endIp }: { startIp: string; endIp: string }) {
 | 
			
		||||
  const cidr = getCidr(start, end);
 | 
			
		||||
  if (cidr != null) {
 | 
			
		||||
    const result: Ipv4RangeExpanderResult = {};
 | 
			
		||||
    result.newEnd = bits2ip(parseInt(cidr.end, 2));
 | 
			
		||||
    result.newStart = bits2ip(parseInt(cidr.start, 2));
 | 
			
		||||
    result.newEnd = bits2ip(Number.parseInt(cidr.end, 2));
 | 
			
		||||
    result.newStart = bits2ip(Number.parseInt(cidr.start, 2));
 | 
			
		||||
    result.newCidr = `${result.newStart}/${cidr.mask}`;
 | 
			
		||||
    result.newSize = getRangesize(cidr.start, cidr.end);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
import jwtDecode, { type JwtHeader, type JwtPayload } from 'jwt-decode';
 | 
			
		||||
import _ from 'lodash';
 | 
			
		||||
import { match } from 'ts-pattern';
 | 
			
		||||
import { ALGORITHM_DESCRIPTIONS, CLAIM_DESCRIPTIONS } from './jwt-parser.constants';
 | 
			
		||||
 | 
			
		||||
export { decodeJwt };
 | 
			
		||||
@@ -32,10 +31,15 @@ function parseClaims({ claim, value }: { claim: string; value: unknown }) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getFriendlyValue({ claim, value }: { claim: string; value: unknown }) {
 | 
			
		||||
  return match(claim)
 | 
			
		||||
    .with('exp', 'nbf', 'iat', () => dateFormatter(value))
 | 
			
		||||
    .with('alg', () => (_.isString(value) ? ALGORITHM_DESCRIPTIONS[value] : undefined))
 | 
			
		||||
    .otherwise(() => undefined);
 | 
			
		||||
  if (['exp', 'nbf', 'iat'].includes(claim)) {
 | 
			
		||||
    return dateFormatter(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (claim === 'alg' && _.isString(value)) {
 | 
			
		||||
    return ALGORITHM_DESCRIPTIONS[value];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return undefined;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function dateFormatter(value: unknown) {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ const getVendorValue = (address: string) => address.trim().replace(/[.:-]/g, '')
 | 
			
		||||
const macAddress = ref('20:37:06:12:34:56');
 | 
			
		||||
const details = computed<string | undefined>(() => db[getVendorValue(macAddress.value)]);
 | 
			
		||||
 | 
			
		||||
const { copy } = useCopy({ source: details, text: 'Vendor info copied to the clipboard' });
 | 
			
		||||
const { copy } = useCopy({ source: () => details.value ?? '', text: 'Vendor info copied to the clipboard' });
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ export {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function hexToBytes(hex: string) {
 | 
			
		||||
  return (hex.match(/.{1,2}/g) ?? []).map(char => parseInt(char, 16));
 | 
			
		||||
  return (hex.match(/.{1,2}/g) ?? []).map(char => Number.parseInt(char, 16));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function computeHMACSha1(message: string, key: string) {
 | 
			
		||||
@@ -32,7 +32,7 @@ function base32toHex(base32: string) {
 | 
			
		||||
    .map(value => base32Chars.indexOf(value).toString(2).padStart(5, '0'))
 | 
			
		||||
    .join('');
 | 
			
		||||
 | 
			
		||||
  const hex = (bits.match(/.{1,8}/g) ?? []).map(chunk => parseInt(chunk, 2).toString(16).padStart(2, '0')).join('');
 | 
			
		||||
  const hex = (bits.match(/.{1,8}/g) ?? []).map(chunk => Number.parseInt(chunk, 2).toString(16).padStart(2, '0')).join('');
 | 
			
		||||
 | 
			
		||||
  return hex;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { useClipboard } from '@vueuse/core';
 | 
			
		||||
import { useCopy } from '@/composable/copy';
 | 
			
		||||
 | 
			
		||||
const props = defineProps<{ tokens: { previous: string; current: string; next: string } }>();
 | 
			
		||||
const { copy: copyPrevious, copied: previousCopied } = useClipboard();
 | 
			
		||||
const { copy: copyCurrent, copied: currentCopied } = useClipboard();
 | 
			
		||||
const { copy: copyNext, copied: nextCopied } = useClipboard();
 | 
			
		||||
const { copy: copyPrevious, isJustCopied: previousCopied } = useCopy({ createToast: false });
 | 
			
		||||
const { copy: copyCurrent, isJustCopied: currentCopied } = useCopy({ createToast: false });
 | 
			
		||||
const { copy: copyNext, isJustCopied: nextCopied } = useCopy({ createToast: false });
 | 
			
		||||
 | 
			
		||||
const { tokens } = toRefs(props);
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ export { getPasswordCrackTimeEstimation, getCharsetLength };
 | 
			
		||||
 | 
			
		||||
function prettifyExponentialNotation(exponentialNotation: number) {
 | 
			
		||||
  const [base, exponent] = exponentialNotation.toString().split('e');
 | 
			
		||||
  const baseAsNumber = parseFloat(base);
 | 
			
		||||
  const baseAsNumber = Number.parseFloat(base);
 | 
			
		||||
  const prettyBase = baseAsNumber % 1 === 0 ? baseAsNumber.toLocaleString() : baseAsNumber.toFixed(2);
 | 
			
		||||
  return exponent ? `${prettyBase}e${exponent}` : prettyBase;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@ const validationRoman = useValidation({
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { copy: copyRoman } = useCopy({ source: outputRoman, text: 'Roman number copied to the clipboard' });
 | 
			
		||||
const { copy: copyArabic } = useCopy({ source: outputNumeral, text: 'Arabic number copied to the clipboard' });
 | 
			
		||||
const { copy: copyArabic } = useCopy({ source: () => String(outputNumeral), text: 'Arabic number copied to the clipboard' });
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,11 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { type FormatFnOptions, format as formatSQL } from 'sql-formatter';
 | 
			
		||||
import { type FormatOptionsWithLanguage, format as formatSQL } from 'sql-formatter';
 | 
			
		||||
import TextareaCopyable from '@/components/TextareaCopyable.vue';
 | 
			
		||||
import { useStyleStore } from '@/stores/style.store';
 | 
			
		||||
 | 
			
		||||
const inputElement = ref<HTMLElement>();
 | 
			
		||||
const styleStore = useStyleStore();
 | 
			
		||||
const config = reactive<Partial<FormatFnOptions>>({
 | 
			
		||||
const config = reactive<FormatOptionsWithLanguage>({
 | 
			
		||||
  keywordCase: 'upper',
 | 
			
		||||
  useTabs: false,
 | 
			
		||||
  language: 'sql',
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								src/tools/string-obfuscator/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/tools/string-obfuscator/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
import { EyeOff } from '@vicons/tabler';
 | 
			
		||||
import { defineTool } from '../tool';
 | 
			
		||||
 | 
			
		||||
export const tool = defineTool({
 | 
			
		||||
  name: 'String obfuscator',
 | 
			
		||||
  path: '/string-obfuscator',
 | 
			
		||||
  description: 'Obfuscate a string (like a secret, an IBAN, or a token) to make it shareable and identifiable without revealing its content.',
 | 
			
		||||
  keywords: ['string', 'obfuscator', 'secret', 'token', 'hide', 'obscure', 'mask', 'masking'],
 | 
			
		||||
  component: () => import('./string-obfuscator.vue'),
 | 
			
		||||
  icon: EyeOff,
 | 
			
		||||
  createdAt: new Date('2023-08-16'),
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										20
									
								
								src/tools/string-obfuscator/string-obfuscator.model.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/tools/string-obfuscator/string-obfuscator.model.test.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
import { describe, expect, it } from 'vitest';
 | 
			
		||||
import { obfuscateString } from './string-obfuscator.model';
 | 
			
		||||
 | 
			
		||||
describe('string-obfuscator model', () => {
 | 
			
		||||
  describe('obfuscateString', () => {
 | 
			
		||||
    it('the characters in the middle of the string are replaced by the replacement character', () => {
 | 
			
		||||
      expect(obfuscateString('1234567890')).toBe('1234******');
 | 
			
		||||
      expect(obfuscateString('1234567890', { replacementChar: 'x' })).toBe('1234xxxxxx');
 | 
			
		||||
      expect(obfuscateString('1234567890', { keepFirst: 5 })).toBe('12345*****');
 | 
			
		||||
      expect(obfuscateString('1234567890', { keepFirst: 0, keepLast: 5 })).toBe('*****67890');
 | 
			
		||||
      expect(obfuscateString('1234567890', { keepFirst: 5, keepLast: 5 })).toBe('1234567890');
 | 
			
		||||
      expect(obfuscateString('1234567890', { keepFirst: 2, keepLast: 2, replacementChar: 'x' })).toBe('12xxxxxx90');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('by default, the spaces are kept, they can be removed with the keepSpace option', () => {
 | 
			
		||||
      expect(obfuscateString('12345 67890')).toBe('1234* *****');
 | 
			
		||||
      expect(obfuscateString('12345 67890', { keepSpace: false })).toBe('1234*******');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										35
									
								
								src/tools/string-obfuscator/string-obfuscator.model.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/tools/string-obfuscator/string-obfuscator.model.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
import { get } from '@vueuse/core';
 | 
			
		||||
import { type MaybeRef, computed } from 'vue';
 | 
			
		||||
 | 
			
		||||
export { obfuscateString, useObfuscateString };
 | 
			
		||||
 | 
			
		||||
function obfuscateString(
 | 
			
		||||
  str: string,
 | 
			
		||||
  { replacementChar = '*', keepFirst = 4, keepLast = 0, keepSpace = true }: { replacementChar?: string; keepFirst?: number; keepLast?: number; keepSpace?: boolean } = {}): string {
 | 
			
		||||
  return str
 | 
			
		||||
    .split('')
 | 
			
		||||
    .map((char, index, array) => {
 | 
			
		||||
      if (keepSpace && char === ' ') {
 | 
			
		||||
        return char;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return (index < keepFirst || index >= array.length - keepLast) ? char : replacementChar;
 | 
			
		||||
    })
 | 
			
		||||
    .join('');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function useObfuscateString(
 | 
			
		||||
  str: MaybeRef<string>,
 | 
			
		||||
  config: { replacementChar?: MaybeRef<string>; keepFirst?: MaybeRef<number>; keepLast?: MaybeRef<number>; keepSpace?: MaybeRef<boolean> } = {},
 | 
			
		||||
 | 
			
		||||
) {
 | 
			
		||||
  return computed(() => obfuscateString(
 | 
			
		||||
    get(str),
 | 
			
		||||
    {
 | 
			
		||||
      replacementChar: get(config.replacementChar),
 | 
			
		||||
      keepFirst: get(config.keepFirst),
 | 
			
		||||
      keepLast: get(config.keepLast),
 | 
			
		||||
      keepSpace: get(config.keepSpace),
 | 
			
		||||
    },
 | 
			
		||||
  ));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								src/tools/string-obfuscator/string-obfuscator.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/tools/string-obfuscator/string-obfuscator.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { useObfuscateString } from './string-obfuscator.model';
 | 
			
		||||
import { useCopy } from '@/composable/copy';
 | 
			
		||||
 | 
			
		||||
const str = ref('Lorem ipsum dolor sit amet');
 | 
			
		||||
const keepFirst = ref(4);
 | 
			
		||||
const keepLast = ref(4);
 | 
			
		||||
const keepSpace = ref(true);
 | 
			
		||||
 | 
			
		||||
const obfuscatedString = useObfuscateString(str, { keepFirst, keepLast, keepSpace });
 | 
			
		||||
const { copy } = useCopy({ source: obfuscatedString });
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <c-input-text v-model:value="str" raw-text placeholder="Enter string to obfuscate" label="String to obfuscate:" clearable multiline />
 | 
			
		||||
 | 
			
		||||
    <div mt-4 flex gap-10px>
 | 
			
		||||
      <div>
 | 
			
		||||
        <div>Keep first:</div>
 | 
			
		||||
        <n-input-number v-model:value="keepFirst" min="0" />
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div>
 | 
			
		||||
        <div>Keep last:</div>
 | 
			
		||||
        <n-input-number v-model:value="keepLast" min="0" />
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div>
 | 
			
		||||
        <div mb-5px>
 | 
			
		||||
          Keep spaces:
 | 
			
		||||
        </div>
 | 
			
		||||
        <n-switch v-model:value="keepSpace" />
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <c-card v-if="obfuscatedString" mt-60px max-w-600px flex items-center gap-5px font-mono>
 | 
			
		||||
      <div break-anywhere text-wrap>
 | 
			
		||||
        {{ obfuscatedString }}
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <c-button @click="copy()">
 | 
			
		||||
        <icon-mdi:content-copy />
 | 
			
		||||
      </c-button>
 | 
			
		||||
    </c-card>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
							
								
								
									
										12
									
								
								src/tools/text-diff/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/tools/text-diff/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
import { FileDiff } from '@vicons/tabler';
 | 
			
		||||
import { defineTool } from '../tool';
 | 
			
		||||
 | 
			
		||||
export const tool = defineTool({
 | 
			
		||||
  name: 'Text diff',
 | 
			
		||||
  path: '/text-diff',
 | 
			
		||||
  description: 'Compare two texts and see the differences between them.',
 | 
			
		||||
  keywords: ['text', 'diff', 'compare', 'string', 'text diff', 'code'],
 | 
			
		||||
  component: () => import('./text-diff.vue'),
 | 
			
		||||
  icon: FileDiff,
 | 
			
		||||
  createdAt: new Date('2023-08-16'),
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										5
									
								
								src/tools/text-diff/text-diff.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/tools/text-diff/text-diff.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <c-card w-full important:flex-1 important:pa-0>
 | 
			
		||||
    <c-diff-editor />
 | 
			
		||||
  </c-card>
 | 
			
		||||
</template>
 | 
			
		||||
@@ -15,14 +15,12 @@ export function createToken({
 | 
			
		||||
  length?: number
 | 
			
		||||
  alphabet?: string
 | 
			
		||||
}) {
 | 
			
		||||
  const allAlphabet
 | 
			
		||||
    = alphabet
 | 
			
		||||
    ?? [
 | 
			
		||||
      ...(withUppercase ? 'ABCDEFGHIJKLMOPQRSTUVWXYZ' : ''),
 | 
			
		||||
      ...(withLowercase ? 'abcdefghijklmopqrstuvwxyz' : ''),
 | 
			
		||||
      ...(withNumbers ? '0123456789' : ''),
 | 
			
		||||
      ...(withSymbols ? '.,;:!?./-"\'#{([-|\\@)]=}*+' : ''),
 | 
			
		||||
    ].join('');
 | 
			
		||||
  const allAlphabet = alphabet ?? [
 | 
			
		||||
    withUppercase ? 'ABCDEFGHIJKLMOPQRSTUVWXYZ' : '',
 | 
			
		||||
    withLowercase ? 'abcdefghijklmopqrstuvwxyz' : '',
 | 
			
		||||
    withNumbers ? '0123456789' : '',
 | 
			
		||||
    withSymbols ? '.,;:!?./-"\'#{([-|\\@)]=}*+' : '',
 | 
			
		||||
  ].join(''); ;
 | 
			
		||||
 | 
			
		||||
  return shuffleString(allAlphabet.repeat(length)).substring(0, length);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@ const { copy } = useCopy({ source: uuids, text: 'UUIDs copied to the clipboard'
 | 
			
		||||
    />
 | 
			
		||||
 | 
			
		||||
    <div flex justify-center gap-3>
 | 
			
		||||
      <c-button autofocus @click="copy">
 | 
			
		||||
      <c-button autofocus @click="copy()">
 | 
			
		||||
        Copy
 | 
			
		||||
      </c-button>
 | 
			
		||||
      <c-button @click="refreshUUIDs">
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										68
									
								
								src/ui/c-diff-editor/c-diff-editor.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/ui/c-diff-editor/c-diff-editor.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import * as monaco from 'monaco-editor';
 | 
			
		||||
import { useStyleStore } from '@/stores/style.store';
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(defineProps<{ options?: monaco.editor.IDiffEditorOptions }>(), { options: () => ({}) });
 | 
			
		||||
const { options } = toRefs(props);
 | 
			
		||||
 | 
			
		||||
const editorContainer = ref<HTMLElement | null>(null);
 | 
			
		||||
let editor: monaco.editor.IStandaloneDiffEditor | null = null;
 | 
			
		||||
 | 
			
		||||
monaco.editor.defineTheme('it-tools-dark', {
 | 
			
		||||
  base: 'vs-dark',
 | 
			
		||||
  inherit: true,
 | 
			
		||||
  rules: [],
 | 
			
		||||
  colors: {
 | 
			
		||||
    'editor.background': '#00000000',
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
monaco.editor.defineTheme('it-tools-light', {
 | 
			
		||||
  base: 'vs',
 | 
			
		||||
  inherit: true,
 | 
			
		||||
  rules: [],
 | 
			
		||||
  colors: {
 | 
			
		||||
    'editor.background': '#00000000',
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const styleStore = useStyleStore();
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
  () => styleStore.isDarkTheme,
 | 
			
		||||
  isDarkTheme => monaco.editor.setTheme(isDarkTheme ? 'it-tools-dark' : 'it-tools-light'),
 | 
			
		||||
  { immediate: true },
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
  () => options.value,
 | 
			
		||||
  options => editor?.updateOptions(options),
 | 
			
		||||
  { immediate: true, deep: true },
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
useResizeObserver(editorContainer, () => {
 | 
			
		||||
  editor?.layout();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  if (!editorContainer.value) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  editor = monaco.editor.createDiffEditor(editorContainer.value, {
 | 
			
		||||
    originalEditable: true,
 | 
			
		||||
    minimap: {
 | 
			
		||||
      enabled: false,
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  editor.setModel({
 | 
			
		||||
    original: monaco.editor.createModel('original text', 'txt'),
 | 
			
		||||
    modified: monaco.editor.createModel('modified text', 'txt'),
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div ref="editorContainer" h-600px />
 | 
			
		||||
</template>
 | 
			
		||||
@@ -1,11 +1,17 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { useTheme } from './c-modal.theme';
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  inheritAttrs: false,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(defineProps<{ open?: boolean; centered?: boolean }>(), {
 | 
			
		||||
  open: false,
 | 
			
		||||
  centered: true,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['update:open']);
 | 
			
		||||
 | 
			
		||||
const isOpen = useVModel(props, 'open', emit, { passive: true });
 | 
			
		||||
 | 
			
		||||
const { centered } = toRefs(props);
 | 
			
		||||
@@ -29,10 +35,6 @@ defineExpose({
 | 
			
		||||
  isOpen,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  inheritAttrs: false,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const theme = useTheme();
 | 
			
		||||
const modal = ref();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ const clampHex = (value: number) => Math.max(0, Math.min(255, Math.round(value))
 | 
			
		||||
 | 
			
		||||
function lighten(color: string, amount: number): string {
 | 
			
		||||
  const alpha = color.length === 9 ? color.slice(7) : '';
 | 
			
		||||
  const num = parseInt(color.slice(1, 7), 16);
 | 
			
		||||
  const num = Number.parseInt(color.slice(1, 7), 16);
 | 
			
		||||
 | 
			
		||||
  const r = clampHex(((num >> 16) & 255) + amount);
 | 
			
		||||
  const g = clampHex(((num >> 8) & 255) + amount);
 | 
			
		||||
 
 | 
			
		||||
@@ -7,5 +7,5 @@ export function formatBytes(bytes: number, decimals = 2) {
 | 
			
		||||
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
 | 
			
		||||
  const i = Math.floor(Math.log(bytes) / Math.log(k));
 | 
			
		||||
 | 
			
		||||
  return `${parseFloat((bytes / k ** i).toFixed(decimals))} ${sizes[i]}`;
 | 
			
		||||
  return `${Number.parseFloat((bytes / k ** i).toFixed(decimals))} ${sizes[i]}`;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,20 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "@vue/tsconfig/tsconfig.web.json",
 | 
			
		||||
  "extends": "@vue/tsconfig/tsconfig.json",
 | 
			
		||||
  "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "**/*.d.ts", "node_modules/vite-plugin-pwa/client.d.ts"],
 | 
			
		||||
  "exclude": ["src/**/__tests__/*"],
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "lib": ["ES2021"],
 | 
			
		||||
    "lib": ["ES2022"],
 | 
			
		||||
    "target": "es2022",
 | 
			
		||||
    "module": "es2022",
 | 
			
		||||
    "moduleResolution": "Node",
 | 
			
		||||
    "composite": true,
 | 
			
		||||
    "baseUrl": ".",
 | 
			
		||||
    "paths": {
 | 
			
		||||
      "@/*": ["./src/*"]
 | 
			
		||||
    },
 | 
			
		||||
    "types": ["naive-ui/volar", "unplugin-icons/types/vue", "@intlify/unplugin-vue-i18n/messages"]
 | 
			
		||||
    "types": ["naive-ui/volar", "@intlify/unplugin-vue-i18n/messages", "unplugin-icons/types/vue"],
 | 
			
		||||
    "esModuleInterop": true,
 | 
			
		||||
    "jsx": "preserve",
 | 
			
		||||
    "skipLibCheck": true
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "extends": "@vue/tsconfig/tsconfig.node.json",
 | 
			
		||||
  "extends": "@tsconfig/node18/tsconfig.json",
 | 
			
		||||
  "include": ["vite.config.*"],
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "composite": true,
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,6 @@
 | 
			
		||||
  "compilerOptions": {
 | 
			
		||||
    "composite": true,
 | 
			
		||||
    "lib": [],
 | 
			
		||||
    "types": ["node", "jsdom"]
 | 
			
		||||
    "types": ["node", "jsdom", "unplugin-icons/types/vue"]
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user