diff --git a/components.d.ts b/components.d.ts index f2c3146f..9ae229b3 100644 --- a/components.d.ts +++ b/components.d.ts @@ -50,6 +50,7 @@ declare module '@vue/runtime-core' { 'CModal.demo': typeof import('./src/ui/c-modal/c-modal.demo.vue')['default'] CModalValue: typeof import('./src/ui/c-modal-value/c-modal-value.vue')['default'] 'CModalValue.demo': typeof import('./src/ui/c-modal-value/c-modal-value.demo.vue')['default'] + CMonacoEditor: typeof import('./src/ui/c-monaco-editor/c-monaco-editor.vue')['default'] CollapsibleToolMenu: typeof import('./src/components/CollapsibleToolMenu.vue')['default'] ColorConverter: typeof import('./src/tools/color-converter/color-converter.vue')['default'] ColoredCard: typeof import('./src/components/ColoredCard.vue')['default'] @@ -107,6 +108,7 @@ declare module '@vue/runtime-core' { Ipv4SubnetCalculator: typeof import('./src/tools/ipv4-subnet-calculator/ipv4-subnet-calculator.vue')['default'] Ipv6UlaGenerator: typeof import('./src/tools/ipv6-ula-generator/ipv6-ula-generator.vue')['default'] JsonDiff: typeof import('./src/tools/json-diff/json-diff.vue')['default'] + JsonLinter: typeof import('./src/tools/json-linter/json-linter.vue')['default'] JsonMinify: typeof import('./src/tools/json-minify/json-minify.vue')['default'] JsonToCsv: typeof import('./src/tools/json-to-csv/json-to-csv.vue')['default'] JsonToToml: typeof import('./src/tools/json-to-toml/json-to-toml.vue')['default'] @@ -126,25 +128,23 @@ declare module '@vue/runtime-core' { MenuLayout: typeof import('./src/components/MenuLayout.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'] + NA: typeof import('naive-ui')['NA'] + NAlert: typeof import('naive-ui')['NAlert'] NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] NCode: typeof import('naive-ui')['NCode'] NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] NConfigProvider: typeof import('naive-ui')['NConfigProvider'] - NDivider: typeof import('naive-ui')['NDivider'] NEllipsis: typeof import('naive-ui')['NEllipsis'] NFormItem: typeof import('naive-ui')['NFormItem'] - NGi: typeof import('naive-ui')['NGi'] - NGrid: typeof import('naive-ui')['NGrid'] NH1: typeof import('naive-ui')['NH1'] NH3: typeof import('naive-ui')['NH3'] NIcon: typeof import('naive-ui')['NIcon'] NInputNumber: typeof import('naive-ui')['NInputNumber'] - NLabel: typeof import('naive-ui')['NLabel'] NLayout: typeof import('naive-ui')['NLayout'] NLayoutSider: typeof import('naive-ui')['NLayoutSider'] NMenu: typeof import('naive-ui')['NMenu'] NScrollbar: typeof import('naive-ui')['NScrollbar'] - NSpin: typeof import('naive-ui')['NSpin'] + NSwitch: typeof import('naive-ui')['NSwitch'] 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'] PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] diff --git a/package.json b/package.json index 9f39ff1d..78365062 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "release": "node ./scripts/release.mjs" }, "dependencies": { + "@guolao/vue-monaco-editor": "^1.4.1", "@it-tools/bip39": "^0.0.4", "@it-tools/oggen": "^1.3.0", "@sindresorhus/slugify": "^2.2.1", @@ -65,6 +66,7 @@ "iarna-toml-esm": "^3.0.5", "ibantools": "^4.3.3", "json5": "^2.2.3", + "jsonlint-mod": "^1.7.6", "jwt-decode": "^3.1.2", "libphonenumber-js": "^1.10.28", "lodash": "^4.17.21", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bd6c38c9..aaf57fa0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,6 +5,9 @@ settings: excludeLinksFromLockfile: false dependencies: + '@guolao/vue-monaco-editor': + specifier: ^1.4.1 + version: 1.5.1(monaco-editor@0.43.0)(vue@3.3.4) '@it-tools/bip39': specifier: ^0.0.4 version: 0.0.4 @@ -95,6 +98,9 @@ dependencies: json5: specifier: ^2.2.3 version: 2.2.3 + jsonlint-mod: + specifier: ^1.7.6 + version: 1.7.6 jwt-decode: specifier: ^3.1.2 version: 3.1.2 @@ -2150,6 +2156,22 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@guolao/vue-monaco-editor@1.5.1(monaco-editor@0.43.0)(vue@3.3.4): + resolution: {integrity: sha512-nhbQHDAwsxrdH/yitcrBgAkN8Cae0IEiYe/M3LWK8bSJRfapkbMyfTHE6Gcxsxa/6efSUZAPDo8dJWBDx5GZyA==} + peerDependencies: + '@vue/composition-api': ^1.7.1 + monaco-editor: '>=0.43.0' + vue: ^2.6.14 || >=3.0.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + dependencies: + '@monaco-editor/loader': 1.4.0(monaco-editor@0.43.0) + monaco-editor: 0.43.0 + vue: 3.3.4 + vue-demi: 0.14.7(vue@3.3.4) + dev: false + /@humanwhocodes/config-array@0.11.10: resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==} engines: {node: '>=10.10.0'} @@ -2417,6 +2439,15 @@ packages: resolution: {integrity: sha512-mrC4y8n88BYvgcgzq9bvTlDgFyi2zuvzmPilRvRc3Uz1iIvq8mDhxJ0rHKFUNzPEScpDvJdIujqiDrulMqiudA==} dev: true + /@monaco-editor/loader@1.4.0(monaco-editor@0.43.0): + resolution: {integrity: sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==} + peerDependencies: + monaco-editor: '>= 0.21.0 < 1' + dependencies: + monaco-editor: 0.43.0 + state-local: 1.0.7 + dev: false + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -3351,7 +3382,7 @@ packages: dependencies: '@unhead/dom': 0.5.1 '@unhead/schema': 0.5.1 - '@vueuse/shared': 10.7.2(vue@3.3.4) + '@vueuse/shared': 10.9.0(vue@3.3.4) unhead: 0.5.1 vue: 3.3.4 transitivePeerDependencies: @@ -3993,10 +4024,10 @@ packages: - vue dev: false - /@vueuse/shared@10.7.2(vue@3.3.4): - resolution: {integrity: sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==} + /@vueuse/shared@10.9.0(vue@3.3.4): + resolution: {integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==} dependencies: - vue-demi: 0.14.6(vue@3.3.4) + vue-demi: 0.14.7(vue@3.3.4) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -4006,6 +4037,10 @@ packages: resolution: {integrity: sha512-P1A1vRGFBhITco8Iw4/hvnDYoE/SoVrd71dW1pBFdXJb3vP+pBtoOuhbEKy0ROJGOyzQuqvFibcwzyLlWMqNiQ==} dev: false + /JSV@4.0.2: + resolution: {integrity: sha512-ZJ6wx9xaKJ3yFUhq5/sk82PJMuUyLk277I8mQeyDgCTjGdjWJIvPfaU5LIXaMuaN2UO1X3kZH4+lgphublZUHw==} + dev: false + /abab@2.0.6: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} dev: true @@ -6606,6 +6641,16 @@ packages: graceful-fs: 4.2.11 dev: true + /jsonlint-mod@1.7.6: + resolution: {integrity: sha512-oGuk6E1ehmIpw0w9ttgb2KsDQQgGXBzZczREW8OfxEm9eCQYL9/LCexSnh++0z3AiYGcXpBgqDSx9AAgzl/Bvg==} + engines: {node: '>= 0.6'} + hasBin: true + dependencies: + JSV: 4.0.2 + chalk: 2.4.2 + underscore: 1.13.6 + dev: false + /jsonpointer@5.0.1: resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} engines: {node: '>=0.10.0'} @@ -8196,6 +8241,10 @@ packages: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} dev: true + /state-local@1.0.7: + resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} + dev: false + /std-env@3.3.3: resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==} dev: true @@ -8632,6 +8681,10 @@ packages: mlly: 1.4.2 dev: true + /underscore@1.13.6: + resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} + dev: false + /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} dev: true @@ -9151,8 +9204,8 @@ packages: vue: 3.3.4 dev: false - /vue-demi@0.14.6(vue@3.3.4): - resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==} + /vue-demi@0.14.7(vue@3.3.4): + resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==} engines: {node: '>=12'} hasBin: true requiresBuild: true @@ -9442,6 +9495,7 @@ packages: /workbox-google-analytics@7.0.0: resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} + deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained dependencies: workbox-background-sync: 7.0.0 workbox-core: 7.0.0 diff --git a/src/main.ts b/src/main.ts index 36ba3b7f..cdd79132 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,6 +2,9 @@ import { createApp } from 'vue'; import { createPinia } from 'pinia'; import { createHead } from '@vueuse/head'; +import { install as VueMonacoEditorPlugin, loader } from '@guolao/vue-monaco-editor'; +import * as monaco from 'monaco-editor'; + import { registerSW } from 'virtual:pwa-register'; import { plausible } from './plugins/plausible.plugin'; @@ -13,10 +16,14 @@ import App from './App.vue'; import router from './router'; import { i18nPlugin } from './plugins/i18n.plugin'; +// loaded monaco-editor from `node_modules` +loader.config({ monaco }); + registerSW(); const app = createApp(App); +app.use(VueMonacoEditorPlugin); app.use(createPinia()); app.use(createHead()); app.use(i18nPlugin); diff --git a/src/tools/index.ts b/src/tools/index.ts index aa861c93..9d3579fb 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -6,6 +6,7 @@ import { tool as asciiTextDrawer } from './ascii-text-drawer'; import { tool as textToUnicode } from './text-to-unicode'; import { tool as safelinkDecoder } from './safelink-decoder'; +import { tool as jsonLinter } from './json-linter'; import { tool as pdfSignatureChecker } from './pdf-signature-checker'; import { tool as numeronymGenerator } from './numeronym-generator'; import { tool as macAddressGenerator } from './mac-address-generator'; @@ -142,6 +143,7 @@ export const toolsByCategory: ToolCategory[] = [ crontabGenerator, jsonViewer, jsonMinify, + jsonLinter, jsonToCsv, sqlPrettify, chmodCalculator, diff --git a/src/tools/json-linter/index.ts b/src/tools/json-linter/index.ts new file mode 100644 index 00000000..d23420f3 --- /dev/null +++ b/src/tools/json-linter/index.ts @@ -0,0 +1,12 @@ +import { Braces } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'JSON Linter', + path: '/json-linter', + description: 'Check and lint JSON content', + keywords: ['json', 'linter', 'check'], + component: () => import('./json-linter.vue'), + icon: Braces, + createdAt: new Date('2024-03-20'), +}); diff --git a/src/tools/json-linter/json-linter.vue b/src/tools/json-linter/json-linter.vue new file mode 100644 index 00000000..45c56bc6 --- /dev/null +++ b/src/tools/json-linter/json-linter.vue @@ -0,0 +1,55 @@ + + + diff --git a/src/tools/json-linter/jsonlint-mod.d.ts b/src/tools/json-linter/jsonlint-mod.d.ts new file mode 100644 index 00000000..27d01b1f --- /dev/null +++ b/src/tools/json-linter/jsonlint-mod.d.ts @@ -0,0 +1,11 @@ +declare module 'jsonlint-mod'{ +/** + * Parse a JSON string to Typescript Object. If there is an error will print it + * as human readible. + * + * Please use `import * as jsonlint from 'jsonlint';`. Instead of, + * `import {parse} from 'jsonlint';`. Otherwise, it cannot reference to the + * correct instance. + */ +export function parse(str: string): Record; +} \ No newline at end of file diff --git a/src/ui/c-monaco-editor/c-monaco-editor.vue b/src/ui/c-monaco-editor/c-monaco-editor.vue new file mode 100644 index 00000000..e3b53437 --- /dev/null +++ b/src/ui/c-monaco-editor/c-monaco-editor.vue @@ -0,0 +1,124 @@ + + + + +