diff options
-rw-r--r-- | components.d.ts | 4 | ||||
-rw-r--r-- | src/tools/index.ts | 2 | ||||
-rw-r--r-- | src/tools/yaml-viewer/index.ts | 12 | ||||
-rw-r--r-- | src/tools/yaml-viewer/yaml-models.ts | 24 | ||||
-rw-r--r-- | src/tools/yaml-viewer/yaml-viewer.vue | 72 |
5 files changed, 111 insertions, 3 deletions
diff --git a/components.d.ts b/components.d.ts index caac9a8..fabbe79 100644 --- a/components.d.ts +++ b/components.d.ts @@ -91,7 +91,6 @@ declare module '@vue/runtime-core' { 'IconMdi:contentCopy': typeof import('~icons/mdi/content-copy')['default'] 'IconMdi:kettleSteamOutline': typeof import('~icons/mdi/kettle-steam-outline')['default'] IconMdiArrowDown: typeof import('~icons/mdi/arrow-down')['default'] - IconMdiArrowRight: typeof import('~icons/mdi/arrow-right')['default'] IconMdiArrowRightBottom: typeof import('~icons/mdi/arrow-right-bottom')['default'] IconMdiCamera: typeof import('~icons/mdi/camera')['default'] IconMdiChevronDown: typeof import('~icons/mdi/chevron-down')['default'] @@ -171,8 +170,6 @@ declare module '@vue/runtime-core' { NTable: typeof import('naive-ui')['NTable'] NTag: typeof import('naive-ui')['NTag'] NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] - NUpload: typeof import('naive-ui')['NUpload'] - NUploadDragger: typeof import('naive-ui')['NUploadDragger'] 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'] PdfSignatureChecker: typeof import('./src/tools/pdf-signature-checker/pdf-signature-checker.vue')['default'] @@ -214,5 +211,6 @@ declare module '@vue/runtime-core' { XmlFormatter: typeof import('./src/tools/xml-formatter/xml-formatter.vue')['default'] YamlToJson: typeof import('./src/tools/yaml-to-json-converter/yaml-to-json.vue')['default'] YamlToToml: typeof import('./src/tools/yaml-to-toml/yaml-to-toml.vue')['default'] + YamlViewer: typeof import('./src/tools/yaml-viewer/yaml-viewer.vue')['default'] } } diff --git a/src/tools/index.ts b/src/tools/index.ts index 2b95577..2a477ed 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -76,6 +76,7 @@ import { tool as urlParser } from './url-parser'; import { tool as uuidGenerator } from './uuid-generator'; import { tool as macAddressLookup } from './mac-address-lookup'; import { tool as xmlFormatter } from './xml-formatter'; +import { tool as yamlViewer } from './yaml-viewer'; export const toolsByCategory: ToolCategory[] = [ { @@ -141,6 +142,7 @@ export const toolsByCategory: ToolCategory[] = [ chmodCalculator, dockerRunToDockerComposeConverter, xmlFormatter, + yamlViewer, ], }, { diff --git a/src/tools/yaml-viewer/index.ts b/src/tools/yaml-viewer/index.ts new file mode 100644 index 0000000..4ba6ced --- /dev/null +++ b/src/tools/yaml-viewer/index.ts @@ -0,0 +1,12 @@ +import { AlignJustified } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'YAML prettify and format', + path: '/yaml-prettify', + description: 'Prettify your YAML string to a human friendly readable format.', + keywords: ['yaml', 'viewer', 'prettify', 'format'], + component: () => import('./yaml-viewer.vue'), + icon: AlignJustified, + createdAt: new Date('2024-01-31'), +}); diff --git a/src/tools/yaml-viewer/yaml-models.ts b/src/tools/yaml-viewer/yaml-models.ts new file mode 100644 index 0000000..54569db --- /dev/null +++ b/src/tools/yaml-viewer/yaml-models.ts @@ -0,0 +1,24 @@ +import { type MaybeRef, get } from '@vueuse/core'; + +import yaml from 'yaml'; + +export { formatYaml }; + +function formatYaml({ + rawYaml, + sortKeys = false, + indentSize = 2, +}: { + rawYaml: MaybeRef<string> + sortKeys?: MaybeRef<boolean> + indentSize?: MaybeRef<number> +}) { + const parsedYaml = yaml.parse(get(rawYaml)); + + const formattedYAML = yaml.stringify(parsedYaml, { + sortMapEntries: get(sortKeys), + indent: get(indentSize), + }); + + return formattedYAML; +} diff --git a/src/tools/yaml-viewer/yaml-viewer.vue b/src/tools/yaml-viewer/yaml-viewer.vue new file mode 100644 index 0000000..3385eee --- /dev/null +++ b/src/tools/yaml-viewer/yaml-viewer.vue @@ -0,0 +1,72 @@ +<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.', + }, + ], +}); +</script> + +<template> + <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"> + <n-switch v-model:value="sortKeys" /> + </n-form-item> + <n-form-item label="Indent size :" label-placement="left" label-width="100" :show-feedback="false"> + <n-input-number v-model:value="indentSize" min="1" max="10" style="width: 100px" /> + </n-form-item> + </div> + </div> + + <n-form-item + label="Your raw YAML" + :feedback="rawYamlValidation.message" + :validation-status="rawYamlValidation.status" + > + <c-input-text + ref="inputElement" + v-model:value="rawYaml" + placeholder="Paste your raw YAML here..." + rows="20" + multiline + autocomplete="off" + autocorrect="off" + autocapitalize="off" + spellcheck="false" + monospace + /> + </n-form-item> + <n-form-item label="Prettified version of your YAML"> + <TextareaCopyable :value="cleanYaml" language="yaml" :follow-height-of="inputElement" /> + </n-form-item> +</template> + +<style lang="less" scoped> +.result-card { + position: relative; + .copy-button { + position: absolute; + top: 10px; + right: 10px; + } +} +</style> |