aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--components.d.ts4
-rw-r--r--src/tools/index.ts2
-rw-r--r--src/tools/yaml-viewer/index.ts12
-rw-r--r--src/tools/yaml-viewer/yaml-models.ts24
-rw-r--r--src/tools/yaml-viewer/yaml-viewer.vue72
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>