mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-05-04 13:29:13 -04:00
Merge df343d11f5
into 76a19d218d
This commit is contained in:
commit
347c48e2b5
12 changed files with 214 additions and 1 deletions
16
components.d.ts
vendored
16
components.d.ts
vendored
|
@ -89,7 +89,9 @@ declare module '@vue/runtime-core' {
|
|||
HttpStatusCodes: typeof import('./src/tools/http-status-codes/http-status-codes.vue')['default']
|
||||
IbanValidatorAndParser: typeof import('./src/tools/iban-validator-and-parser/iban-validator-and-parser.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']
|
||||
IconMdiArrowDown: typeof import('~icons/mdi/arrow-down')['default']
|
||||
IconMdiChevronDown: typeof import('~icons/mdi/chevron-down')['default']
|
||||
IconMdiChevronRight: typeof import('~icons/mdi/chevron-right')['default']
|
||||
IconMdiClose: typeof import('~icons/mdi/close')['default']
|
||||
|
@ -108,6 +110,7 @@ declare module '@vue/runtime-core' {
|
|||
Ipv6UlaGenerator: typeof import('./src/tools/ipv6-ula-generator/ipv6-ula-generator.vue')['default']
|
||||
JsonDiff: typeof import('./src/tools/json-diff/json-diff.vue')['default']
|
||||
JsonMinify: typeof import('./src/tools/json-minify/json-minify.vue')['default']
|
||||
JsonSortMaster: typeof import('./src/tools/json-sort-master/json-sort-master.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']
|
||||
JsonToYaml: typeof import('./src/tools/json-to-yaml-converter/json-to-yaml.vue')['default']
|
||||
|
@ -126,25 +129,38 @@ 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']
|
||||
NCheckbox: typeof import('naive-ui')['NCheckbox']
|
||||
NCode: typeof import('naive-ui')['NCode']
|
||||
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
|
||||
NColorPicker: typeof import('naive-ui')['NColorPicker']
|
||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||
NDatePicker: typeof import('naive-ui')['NDatePicker']
|
||||
NDivider: typeof import('naive-ui')['NDivider']
|
||||
NEllipsis: typeof import('naive-ui')['NEllipsis']
|
||||
NForm: typeof import('naive-ui')['NForm']
|
||||
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']
|
||||
NImage: typeof import('naive-ui')['NImage']
|
||||
NInputGroup: typeof import('naive-ui')['NInputGroup']
|
||||
NInputGroupLabel: typeof import('naive-ui')['NInputGroupLabel']
|
||||
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']
|
||||
NSlider: typeof import('naive-ui')['NSlider']
|
||||
NSpin: typeof import('naive-ui')['NSpin']
|
||||
NStatistic: typeof import('naive-ui')['NStatistic']
|
||||
NSwitch: typeof import('naive-ui')['NSwitch']
|
||||
NTable: typeof import('naive-ui')['NTable']
|
||||
NTag: typeof import('naive-ui')['NTag']
|
||||
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']
|
||||
|
|
|
@ -328,6 +328,10 @@ tools:
|
|||
title: PDF signature checker
|
||||
description: Verify the signatures of a PDF file. A signed PDF file contains one or more signatures that may be used to determine whether the contents of the file have been altered since the file was signed.
|
||||
|
||||
json-sort-master:
|
||||
title: JSON sort master
|
||||
description: Sort your JSON by keys and values.
|
||||
|
||||
json-minify:
|
||||
title: JSON minify
|
||||
description: Minify and compress your JSON by removing unnecessary whitespace.
|
||||
|
|
|
@ -69,3 +69,7 @@ tools:
|
|||
measurement: Measurement
|
||||
text: Text
|
||||
data: Data
|
||||
|
||||
json-sort-master:
|
||||
title: Maestro de clasificación JSON
|
||||
description: Ordena tu JSON por claves y valores.
|
|
@ -79,3 +79,7 @@ tools:
|
|||
copied: Le token a été copié
|
||||
length: Longueur
|
||||
tokenPlaceholder: Le token...
|
||||
|
||||
json-sort-master:
|
||||
title: Maître de tri JSON
|
||||
description: Triez votre JSON par clés et valeurs.
|
|
@ -69,3 +69,7 @@ tools:
|
|||
measurement: 'Medidas'
|
||||
text: 'Texto'
|
||||
data: 'Dados'
|
||||
|
||||
json-sort-master:
|
||||
title: 'Mestre de classificação JSON'
|
||||
description: 'Ordene seu JSON por chaves e valores.'
|
||||
|
|
|
@ -69,3 +69,7 @@ tools:
|
|||
measurement: Вимірювання
|
||||
text: Текст
|
||||
data: Дані
|
||||
|
||||
json-sort-master:
|
||||
title: JSON сортувальник
|
||||
description: Сортуйте ваш JSON за ключами та значеннями.
|
||||
|
|
|
@ -221,6 +221,10 @@ tools:
|
|||
title: Định dạng và làm đẹp JSON
|
||||
description: Định dạng chuỗi JSON của bạn thành một định dạng dễ đọc và thân thiện với con người.
|
||||
|
||||
json-sort-master:
|
||||
title: Sắp xếp JSON
|
||||
description: Sắp xếp JSON của bạn theo các khóa và giá trị.
|
||||
|
||||
docker-run-to-docker-compose-converter:
|
||||
title: Chuyển đổi lệnh docker run thành tệp docker-compose
|
||||
description: Chuyển đổi các lệnh docker run thành tệp docker-compose!
|
||||
|
|
|
@ -225,6 +225,10 @@ tools:
|
|||
title: JSON美化和格式化
|
||||
description: 将JSON字符串修饰为友好的可读格式。
|
||||
|
||||
json-sort-master:
|
||||
title: JSON排序大师
|
||||
description: 按键和值对您的JSON进行排序。
|
||||
|
||||
docker-run-to-docker-compose-converter:
|
||||
title: Docker Run 到 docker-compose 转换器
|
||||
description: 将 docker run 命令行转换为 docker-compose 文件!
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
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 jsonSortMaster } from './json-sort-master';
|
||||
|
||||
import { tool as asciiTextDrawer } from './ascii-text-drawer';
|
||||
|
||||
|
@ -104,6 +105,7 @@ export const toolsByCategory: ToolCategory[] = [
|
|||
yamlToToml,
|
||||
jsonToYaml,
|
||||
jsonToToml,
|
||||
jsonSortMaster,
|
||||
listConverter,
|
||||
tomlToJson,
|
||||
tomlToYaml,
|
||||
|
|
13
src/tools/json-sort-master/index.ts
Normal file
13
src/tools/json-sort-master/index.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { ArrowsSort } from '@vicons/tabler';
|
||||
import { defineTool } from '../tool';
|
||||
import { translate } from '@/plugins/i18n.plugin';
|
||||
|
||||
export const tool = defineTool({
|
||||
name: translate('tools.json-sort-master.title'),
|
||||
path: '/json-sort-master',
|
||||
description: translate('tools.json-sort-master.description'),
|
||||
keywords: ['json', 'sort'],
|
||||
component: () => import('./json-sort-master.vue'),
|
||||
icon: ArrowsSort,
|
||||
createdAt: new Date('2024-03-27'),
|
||||
});
|
80
src/tools/json-sort-master/json-sort-master.vue
Normal file
80
src/tools/json-sort-master/json-sort-master.vue
Normal file
|
@ -0,0 +1,80 @@
|
|||
<script setup lang="ts">
|
||||
import JSON5 from 'json5';
|
||||
import { useStorage } from '@vueuse/core';
|
||||
import { formatJson } from './json.models';
|
||||
import { withDefaultOnError } from '@/utils/defaults';
|
||||
import { useValidation } from '@/composable/validation';
|
||||
import TextareaCopyable from '@/components/TextareaCopyable.vue';
|
||||
|
||||
const inputElement = ref<HTMLElement>();
|
||||
|
||||
const rawJson = useStorage('json-prettify:raw-json', '{"hello": "world", "foo": "bar"}');
|
||||
const sortMethod = useStorage('json-prettify:sort-method', 'key_name');
|
||||
const indentSize = useStorage('json-prettify:indent-size', 3);
|
||||
const keyName = ref('');
|
||||
const cleanJson = computed(() => withDefaultOnError(() => formatJson({ rawJson, sortMethod, keyName, indentSize }), ''));
|
||||
|
||||
const rawJsonValidation = useValidation({
|
||||
source: rawJson,
|
||||
rules: [
|
||||
{
|
||||
validator: v => v === '' || JSON5.parse(v),
|
||||
message: 'Provided JSON is not valid.',
|
||||
},
|
||||
],
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div style="flex: 0 0 100%">
|
||||
<div style="margin: 0 auto; max-width: 400px" flex justify-center gap-3>
|
||||
<c-select
|
||||
v-model:value="sortMethod" mb-4 style="width: 200px" label="Sort Method" :options="[
|
||||
{
|
||||
label: 'Key Name',
|
||||
value: 'key_name',
|
||||
},
|
||||
{
|
||||
label: 'Key Value',
|
||||
value: 'key_val',
|
||||
},
|
||||
{
|
||||
label: 'Key Name (Descending)',
|
||||
value: 'key_name_desc',
|
||||
},
|
||||
{
|
||||
label: 'Key Value (Descending)',
|
||||
value: 'key_val_desc',
|
||||
},
|
||||
]"
|
||||
/>
|
||||
|
||||
<c-input-text v-if="!['key_name', 'key_name_desc'].includes(sortMethod)" v-model:value="keyName" label="Key Name:" style="width: 200px" clearable raw-text />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<n-form-item
|
||||
label="Your raw JSON" :feedback="rawJsonValidation.message"
|
||||
:validation-status="rawJsonValidation.status"
|
||||
>
|
||||
<c-input-text
|
||||
ref="inputElement" v-model:value="rawJson" placeholder="Paste your raw JSON here..." rows="20"
|
||||
multiline autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" monospace
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="Sorted version of your JSON">
|
||||
<TextareaCopyable :value="cleanJson" language="json" :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>
|
74
src/tools/json-sort-master/json.models.ts
Normal file
74
src/tools/json-sort-master/json.models.ts
Normal file
|
@ -0,0 +1,74 @@
|
|||
import { type MaybeRef, get } from '@vueuse/core';
|
||||
import JSON5 from 'json5';
|
||||
|
||||
export { sortObjectKeys, sortObjectValues, formatJson };
|
||||
|
||||
function sortObjectKeys<T>(obj: T, sortMethod: string): T {
|
||||
if (typeof obj !== 'object' || obj === null) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map(value => sortObjectKeys(value, sortMethod)) as unknown as T;
|
||||
}
|
||||
|
||||
return Object.keys(obj)
|
||||
.sort((a, b) => sortMethod === 'key_name' ? a.localeCompare(b) : b.localeCompare(a))
|
||||
.reduce((sortedObj, key) => {
|
||||
sortedObj[key] = sortObjectKeys((obj as Record<string, unknown>)[key], sortMethod);
|
||||
return sortedObj;
|
||||
}, {} as Record<string, unknown>) as T;
|
||||
}
|
||||
|
||||
function sortObjectValues<T>(obj: T, sortMethod: string, keyName: string): T {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.sort((a, b) => {
|
||||
const valueA = a[keyName];
|
||||
const valueB = b[keyName];
|
||||
|
||||
if (typeof valueA === 'number' && typeof valueB === 'number') {
|
||||
return sortMethod === 'key_val' ? valueA - valueB : valueB - valueA;
|
||||
}
|
||||
if (typeof valueA === 'string' && typeof valueB === 'string') {
|
||||
return sortMethod === 'key_val' ? valueA.localeCompare(valueB) : valueB.localeCompare(valueA);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof obj === 'object' && obj !== null) {
|
||||
const sortedKeys = Object.keys(obj).sort((a, b) => {
|
||||
if (sortMethod === 'key_val') {
|
||||
return a.localeCompare(b);
|
||||
}
|
||||
return b.localeCompare(a);
|
||||
});
|
||||
|
||||
return sortedKeys.reduce((sortedObj, key) => {
|
||||
sortedObj[key] = sortObjectValues((obj as Record<string, unknown>)[key], sortMethod, keyName);
|
||||
return sortedObj;
|
||||
}, {} as Record<string, unknown>) as T;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function formatJson({
|
||||
rawJson,
|
||||
sortMethod = 'key_name',
|
||||
keyName = '',
|
||||
indentSize = 3,
|
||||
}: {
|
||||
rawJson: MaybeRef<string>
|
||||
sortMethod: MaybeRef<string>
|
||||
keyName: MaybeRef<string>
|
||||
indentSize?: MaybeRef<number>
|
||||
}) {
|
||||
const parsedObject = JSON5.parse(get(rawJson));
|
||||
|
||||
if (['key_name', 'key_name_desc'].includes(get(sortMethod))) {
|
||||
return JSON.stringify(sortObjectKeys(parsedObject, get(sortMethod)), null, get(indentSize));
|
||||
}
|
||||
|
||||
return JSON.stringify(sortObjectValues(parsedObject, get(sortMethod), get(keyName)), null, get(indentSize));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue