mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-05-05 05:47:10 -04:00
feat(Yaml Viewer): add parsing validation
Add parsing validations Fix #540
This commit is contained in:
parent
d3b32cc14e
commit
fd0a723f06
6 changed files with 123 additions and 65 deletions
3
components.d.ts
vendored
3
components.d.ts
vendored
|
@ -126,6 +126,7 @@ 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']
|
||||
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']
|
||||
|
@ -145,6 +146,7 @@ declare module '@vue/runtime-core' {
|
|||
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']
|
||||
|
@ -159,6 +161,7 @@ declare module '@vue/runtime-core' {
|
|||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
RsaKeyPairGenerator: typeof import('./src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue')['default']
|
||||
SafelinkDecoder: typeof import('./src/tools/safelink-decoder/safelink-decoder.vue')['default']
|
||||
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']
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
"change-case": "^4.1.2",
|
||||
"colord": "^2.9.3",
|
||||
"composerize-ts": "^0.6.2",
|
||||
"composeverter": "^1.7.2",
|
||||
"country-code-lookup": "^0.1.0",
|
||||
"cron-validator": "^1.3.1",
|
||||
"cronstrue": "^2.26.0",
|
||||
|
|
48
pnpm-lock.yaml
generated
48
pnpm-lock.yaml
generated
|
@ -53,6 +53,9 @@ dependencies:
|
|||
composerize-ts:
|
||||
specifier: ^0.6.2
|
||||
version: 0.6.2
|
||||
composeverter:
|
||||
specifier: ^1.7.2
|
||||
version: 1.7.2
|
||||
country-code-lookup:
|
||||
specifier: ^0.1.0
|
||||
version: 0.1.0
|
||||
|
@ -3351,7 +3354,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 +3996,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
|
||||
|
@ -4051,6 +4054,14 @@ packages:
|
|||
- supports-color
|
||||
dev: true
|
||||
|
||||
/ajv-errors@3.0.0(ajv@8.12.0):
|
||||
resolution: {integrity: sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==}
|
||||
peerDependencies:
|
||||
ajv: ^8.0.1
|
||||
dependencies:
|
||||
ajv: 8.12.0
|
||||
dev: false
|
||||
|
||||
/ajv@6.12.6:
|
||||
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
|
||||
dependencies:
|
||||
|
@ -4067,7 +4078,6 @@ packages:
|
|||
json-schema-traverse: 1.0.0
|
||||
require-from-string: 2.0.2
|
||||
uri-js: 4.4.1
|
||||
dev: true
|
||||
|
||||
/ansi-colors@4.1.3:
|
||||
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
|
||||
|
@ -4560,6 +4570,15 @@ packages:
|
|||
yamljs: 0.3.0
|
||||
dev: false
|
||||
|
||||
/composeverter@1.7.2:
|
||||
resolution: {integrity: sha512-gRSCkSU8wJQvmTHQ23wBd2gCdUsns95k3lL7YszZBu5EyA3eac46mI7nVgvk1pZTM0mOmj/E5yurtdYkuVNZRA==}
|
||||
dependencies:
|
||||
ajv: 8.12.0
|
||||
ajv-errors: 3.0.0(ajv@8.12.0)
|
||||
core-js: 2.6.12
|
||||
yaml: 1.10.2
|
||||
dev: false
|
||||
|
||||
/concat-map@0.0.1:
|
||||
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
|
||||
|
||||
|
@ -4613,6 +4632,12 @@ packages:
|
|||
browserslist: 4.22.1
|
||||
dev: true
|
||||
|
||||
/core-js@2.6.12:
|
||||
resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==}
|
||||
deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
|
||||
/country-code-lookup@0.1.0:
|
||||
resolution: {integrity: sha512-IOI66HEG+8bXfWPy+sTzuN7161vmDZOHg1wgIPFf3WfD73FeLajnn6C+fnxOIa9RL1WRBDMXQQWW/FOaOYaQ3w==}
|
||||
dev: false
|
||||
|
@ -6571,7 +6596,6 @@ packages:
|
|||
|
||||
/json-schema-traverse@1.0.0:
|
||||
resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
|
||||
dev: true
|
||||
|
||||
/json-schema@0.4.0:
|
||||
resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
|
||||
|
@ -7666,7 +7690,6 @@ packages:
|
|||
/punycode@2.3.0:
|
||||
resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/punycode@2.3.1:
|
||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||
|
@ -7814,7 +7837,6 @@ packages:
|
|||
/require-from-string@2.0.2:
|
||||
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/require-main-filename@2.0.0:
|
||||
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
|
||||
|
@ -8913,7 +8935,6 @@ packages:
|
|||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||
dependencies:
|
||||
punycode: 2.3.0
|
||||
dev: true
|
||||
|
||||
/url-parse@1.5.10:
|
||||
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
|
||||
|
@ -9151,8 +9172,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
|
||||
|
@ -9579,6 +9600,11 @@ packages:
|
|||
yaml: 2.2.1
|
||||
dev: true
|
||||
|
||||
/yaml@1.10.2:
|
||||
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: false
|
||||
|
||||
/yaml@2.2.1:
|
||||
resolution: {integrity: sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==}
|
||||
engines: {node: '>= 14'}
|
||||
|
|
20
src/tools/yaml-viewer/composeverter.d.ts
vendored
Normal file
20
src/tools/yaml-viewer/composeverter.d.ts
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
declare module 'composeverter' {
|
||||
interface Configuration {
|
||||
expandVolumes?: boolean;
|
||||
expandPorts?: boolean;
|
||||
indent?: number;
|
||||
}
|
||||
interface DockerComposeValidatioError {
|
||||
line?: number;
|
||||
message: string;
|
||||
helpLink?: string;
|
||||
}
|
||||
export function validateDockerComposeToCommonSpec(content: string): DockerComposeValidatioError[];
|
||||
export function migrateFromV2xToV3x(content: string, configuration?: Configuration = null): string;
|
||||
export function migrateFromV3xToV2x(content: string, configuration?: Configuration = null): string;
|
||||
export function migrateFromV1ToV2x(content: string, configuration?: Configuration = null): string;
|
||||
export function migrateToCommonSpec(content: string, configuration?: Configuration = null): string;
|
||||
export function migrateFromV2xToV3x(content: string, configuration?: Configuration = null): string;
|
||||
export function getDockerComposeSchemaWithoutFormats(): object;
|
||||
export function yamlParse(content: string): object;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { type MaybeRef, get } from '@vueuse/core';
|
||||
|
||||
import { yamlParse } from 'composeverter';
|
||||
import yaml from 'yaml';
|
||||
|
||||
export { formatYaml };
|
||||
|
@ -13,7 +13,7 @@ function formatYaml({
|
|||
sortKeys?: MaybeRef<boolean>
|
||||
indentSize?: MaybeRef<number>
|
||||
}) {
|
||||
const parsedYaml = yaml.parse(get(rawYaml));
|
||||
const parsedYaml = yamlParse(get(rawYaml));
|
||||
|
||||
const formattedYAML = yaml.stringify(parsedYaml, {
|
||||
sortMapEntries: get(sortKeys),
|
||||
|
|
|
@ -1,31 +1,32 @@
|
|||
<script setup lang="ts">
|
||||
import yaml from 'yaml';
|
||||
import { useStorage } from '@vueuse/core';
|
||||
import { formatYaml } from './yaml-models';
|
||||
import { withDefaultOnError } from '@/utils/defaults';
|
||||
import { useValidation } from '@/composable/validation';
|
||||
import TextareaCopyable from '@/components/TextareaCopyable.vue';
|
||||
|
||||
const inputElement = ref<HTMLElement>();
|
||||
|
||||
const rawYaml = useStorage('yaml-prettify:raw-yaml', '');
|
||||
const indentSize = useStorage('yaml-prettify:indent-size', 2);
|
||||
const sortKeys = useStorage('yaml-prettify:sort-keys', false);
|
||||
|
||||
const cleanYaml = computed(() => withDefaultOnError(() => formatYaml({ rawYaml, indentSize, sortKeys }), ''));
|
||||
|
||||
const rawYamlValidation = useValidation({
|
||||
source: rawYaml,
|
||||
rules: [
|
||||
{
|
||||
validator: v => v === '' || yaml.parse(v),
|
||||
message: 'Provided YAML is not valid.',
|
||||
},
|
||||
],
|
||||
const yamlFormattingResult = computed(() => {
|
||||
try {
|
||||
return { yaml: formatYaml({ rawYaml, indentSize, sortKeys }), errors: [] };
|
||||
}
|
||||
catch (e: any) {
|
||||
return { yaml: '#see error messages', errors: e.toString().split('\n') };
|
||||
}
|
||||
});
|
||||
const errors = computed(() => yamlFormattingResult.value.errors);
|
||||
const cleanYaml = computed(() => yamlFormattingResult.value.yaml);
|
||||
|
||||
const MONACO_EDITOR_OPTIONS = {
|
||||
automaticLayout: true,
|
||||
formatOnType: true,
|
||||
formatOnPaste: true,
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div max-w-600>
|
||||
<div style="flex: 0 0 100%">
|
||||
<div style="margin: 0 auto; max-width: 600px" flex justify-center gap-3>
|
||||
<n-form-item label="Sort keys :" label-placement="left" label-width="100">
|
||||
|
@ -37,36 +38,43 @@ const rawYamlValidation = useValidation({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<n-form-item
|
||||
label="Your raw YAML"
|
||||
:feedback="rawYamlValidation.message"
|
||||
:validation-status="rawYamlValidation.status"
|
||||
>
|
||||
<c-input-text
|
||||
ref="inputElement"
|
||||
<c-label label="Your raw YAML:">
|
||||
<div relative w-full>
|
||||
<c-monaco-editor
|
||||
v-model:value="rawYaml"
|
||||
placeholder="Paste your raw YAML here..."
|
||||
rows="20"
|
||||
multiline
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
autocapitalize="off"
|
||||
spellcheck="false"
|
||||
monospace
|
||||
theme="vs-dark"
|
||||
language="yaml"
|
||||
height="250px"
|
||||
:options="MONACO_EDITOR_OPTIONS"
|
||||
/>
|
||||
</n-form-item>
|
||||
</div>
|
||||
</c-label>
|
||||
|
||||
<div v-if="errors.length > 0">
|
||||
<n-alert title="The following errors occured" type="error" mt-5>
|
||||
<ul>
|
||||
<li v-for="(message, index) of errors" :key="index">
|
||||
{{ message }}
|
||||
</li>
|
||||
</ul>
|
||||
</n-alert>
|
||||
</div>
|
||||
|
||||
<n-divider />
|
||||
|
||||
<n-form-item label="Prettified version of your YAML">
|
||||
<TextareaCopyable :value="cleanYaml" language="yaml" :follow-height-of="inputElement" />
|
||||
<TextareaCopyable :value="cleanYaml" language="yaml" />
|
||||
</n-form-item>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.result-card {
|
||||
<style lang="less" scoped>
|
||||
.result-card {
|
||||
position: relative;
|
||||
.copy-button {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue