feat: minify json

This commit is contained in:
Ibrahima G. Coulibaly
2025-03-08 06:43:11 +00:00
parent 4a956bf916
commit 90d3c0801e
10 changed files with 211 additions and 103 deletions

129
.idea/workspace.xml generated
View File

@@ -4,11 +4,17 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="fix: replace text service">
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="chore: smooth scroll for use this tool and examles">
<change afterPath="$PROJECT_DIR$/src/pages/tools/json/minify/index.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/pages/tools/json/minify/meta.ts" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/pages/tools/json/minify/service.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/string/quote/meta.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/string/quote/meta.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/string/rot13/meta.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/string/rot13/meta.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/string/rotate/meta.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/string/rotate/meta.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/ToolContent.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/ToolContent.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/examples/ExampleCard.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/examples/ExampleCard.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/examples/ExampleOptions.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/examples/ExampleOptions.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/examples/ToolExamples.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/examples/ToolExamples.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/components/options/ToolOptions.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/options/ToolOptions.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/json/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/json/index.ts" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -22,9 +28,10 @@
<option name="BRANCH" value="origin/main" />
</component>
<component name="Git.Settings">
<option name="PUSH_AUTO_UPDATE" value="true" />
<option name="RECENT_BRANCH_BY_REPOSITORY">
<map>
<entry key="$PROJECT_DIR$" value="fork/EugSh1/main" />
<entry key="$PROJECT_DIR$" value="truncate" />
</map>
</option>
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
@@ -96,52 +103,52 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"ASKED_ADD_EXTERNAL_FILES": "true",
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
"Docker.Dockerfile build.executor": "Run",
"Docker.Dockerfile.executor": "Run",
"Playwright.JoinText Component.executor": "Run",
"Playwright.JoinText Component.should merge text pieces with specified join character.executor": "Run",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.git.unshallow": "true",
"Vitest.compute function (1).executor": "Run",
"Vitest.compute function.executor": "Run",
"Vitest.mergeText.executor": "Run",
"Vitest.mergeText.should merge lines and preserve blank lines when deleteBlankLines is false.executor": "Run",
"Vitest.mergeText.should merge lines, preserve blank lines and trailing spaces when both deleteBlankLines and deleteTrailingSpaces are false.executor": "Run",
"Vitest.removeDuplicateLines function.executor": "Run",
"Vitest.removeDuplicateLines function.newlines option.executor": "Run",
"Vitest.removeDuplicateLines function.newlines option.should filter newlines when newlines is set to filter.executor": "Run",
"Vitest.replaceText function.executor": "Run",
"git-widget-placeholder": "#22 on truncate",
"ignore.virus.scanning.warn.message": "true",
"kotlin-language-version-configured": "true",
"last_opened_file_path": "C:/Users/Ibrahima/IdeaProjects/omni-tools/public/assets",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"npm.build.executor": "Run",
"npm.dev.executor": "Run",
"npm.lint.executor": "Run",
"npm.prebuild.executor": "Run",
"npm.script:create:tool.executor": "Run",
"npm.test.executor": "Run",
"npm.test:e2e.executor": "Run",
"npm.test:e2e:run.executor": "Run",
"prettierjs.PrettierConfiguration.Package": "C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\prettier",
"project.structure.last.edited": "Problems",
"project.structure.proportion": "0.0",
"project.structure.side.proportion": "0.2",
"settings.editor.selected.configurable": "settings.typescriptcompiler",
"ts.external.directory.path": "C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\typescript\\lib",
"vue.rearranger.settings.migration": "true"
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;ASKED_ADD_EXTERNAL_FILES&quot;: &quot;true&quot;,
&quot;ASKED_SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,
&quot;Docker.Dockerfile build.executor&quot;: &quot;Run&quot;,
&quot;Docker.Dockerfile.executor&quot;: &quot;Run&quot;,
&quot;Playwright.JoinText Component.executor&quot;: &quot;Run&quot;,
&quot;Playwright.JoinText Component.should merge text pieces with specified join character.executor&quot;: &quot;Run&quot;,
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
&quot;Vitest.compute function (1).executor&quot;: &quot;Run&quot;,
&quot;Vitest.compute function.executor&quot;: &quot;Run&quot;,
&quot;Vitest.mergeText.executor&quot;: &quot;Run&quot;,
&quot;Vitest.mergeText.should merge lines and preserve blank lines when deleteBlankLines is false.executor&quot;: &quot;Run&quot;,
&quot;Vitest.mergeText.should merge lines, preserve blank lines and trailing spaces when both deleteBlankLines and deleteTrailingSpaces are false.executor&quot;: &quot;Run&quot;,
&quot;Vitest.removeDuplicateLines function.executor&quot;: &quot;Run&quot;,
&quot;Vitest.removeDuplicateLines function.newlines option.executor&quot;: &quot;Run&quot;,
&quot;Vitest.removeDuplicateLines function.newlines option.should filter newlines when newlines is set to filter.executor&quot;: &quot;Run&quot;,
&quot;Vitest.replaceText function.executor&quot;: &quot;Run&quot;,
&quot;git-widget-placeholder&quot;: &quot;main&quot;,
&quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;,
&quot;kotlin-language-version-configured&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;C:/Users/Ibrahima/IdeaProjects/omni-tools/public/assets&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;npm.build.executor&quot;: &quot;Run&quot;,
&quot;npm.dev.executor&quot;: &quot;Run&quot;,
&quot;npm.lint.executor&quot;: &quot;Run&quot;,
&quot;npm.prebuild.executor&quot;: &quot;Run&quot;,
&quot;npm.script:create:tool.executor&quot;: &quot;Run&quot;,
&quot;npm.test.executor&quot;: &quot;Run&quot;,
&quot;npm.test:e2e.executor&quot;: &quot;Run&quot;,
&quot;npm.test:e2e:run.executor&quot;: &quot;Run&quot;,
&quot;prettierjs.PrettierConfiguration.Package&quot;: &quot;C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\prettier&quot;,
&quot;project.structure.last.edited&quot;: &quot;Problems&quot;,
&quot;project.structure.proportion&quot;: &quot;0.0&quot;,
&quot;project.structure.side.proportion&quot;: &quot;0.2&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;settings.typescriptcompiler&quot;,
&quot;ts.external.directory.path&quot;: &quot;C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\typescript\\lib&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}]]></component>
}</component>
<component name="ReactDesignerToolWindowState">
<option name="myId2Visible">
<map>
@@ -330,14 +337,6 @@
<workItem from="1740923024259" duration="23000" />
<workItem from="1740933006573" duration="3679000" />
</task>
<task id="LOCAL-00093" summary="feat: group list ui">
<option name="closed" value="true" />
<created>1720656867853</created>
<option name="number" value="00093" />
<option name="presentableId" value="LOCAL-00093" />
<option name="project" value="LOCAL" />
<updated>1720656867853</updated>
</task>
<task id="LOCAL-00094" summary="feat: reverse list ui">
<option name="closed" value="true" />
<created>1720658257129</created>
@@ -722,7 +721,15 @@
<option name="project" value="LOCAL" />
<updated>1741211604972</updated>
</task>
<option name="localTasksCounter" value="142" />
<task id="LOCAL-00142" summary="chore: smooth scroll for use this tool and examles">
<option name="closed" value="true" />
<created>1741414797155</created>
<option name="number" value="00142" />
<option name="presentableId" value="LOCAL-00142" />
<option name="project" value="LOCAL" />
<updated>1741414797155</updated>
</task>
<option name="localTasksCounter" value="143" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@@ -781,7 +788,6 @@
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" />
<option name="CHECK_NEW_TODO" value="false" />
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
<MESSAGE value="feat: funding" />
<MESSAGE value="feat: ui changes" />
<MESSAGE value="fix: readme" />
<MESSAGE value="fix: broken links" />
@@ -806,7 +812,8 @@
<MESSAGE value="fix: tsc" />
<MESSAGE value="style: optimizations" />
<MESSAGE value="fix: replace text service" />
<option name="LAST_COMMIT_MESSAGE" value="fix: replace text service" />
<MESSAGE value="chore: smooth scroll for use this tool and examles" />
<option name="LAST_COMMIT_MESSAGE" value="chore: smooth scroll for use this tool and examles" />
</component>
<component name="XSLT-Support.FileAssociations.UIState">
<expand />

View File

@@ -17,7 +17,7 @@ interface ToolContentPropsBase<T, I> extends ToolComponentProps {
// Tool options
initialValues: T;
getGroups: GetGroupsType<T>;
getGroups: GetGroupsType<T> | null;
// Computation function
compute: (optionsValues: T, input: I) => void;

View File

@@ -18,7 +18,7 @@ export interface ExampleCardProps<T> {
sampleResult: string;
sampleOptions: T;
changeInputResult: (newInput: string, newOptions: T) => void;
getGroups: GetGroupsType<T>;
getGroups: GetGroupsType<T> | null;
}
export default function ExampleCard<T>({

View File

@@ -7,12 +7,12 @@ export default function ExampleOptions<T>({
getGroups
}: {
options: T;
getGroups: GetGroupsType<T>;
getGroups: GetGroupsType<T> | null;
}) {
return (
<ToolOptionGroups
// @ts-ignore
groups={getGroups({ values: options })}
groups={getGroups?.({ values: options }) ?? []}
vertical
/>
);

View File

@@ -13,7 +13,7 @@ export interface ExampleProps<T> {
title: string;
subtitle?: string;
exampleCards: CardExampleType<T>[];
getGroups: GetGroupsType<T>;
getGroups: GetGroupsType<T> | null;
formRef: React.RefObject<FormikProps<T>>;
setInput: React.Dispatch<React.SetStateAction<any>>;
}

View File

@@ -86,44 +86,45 @@ export default function ToolOptions<T extends FormikValues>({
validationSchema?: any | (() => any);
compute: (optionsValues: T, input: any) => void;
input?: any;
getGroups: GetGroupsType<T>;
getGroups: GetGroupsType<T> | null;
formRef?: RefObject<FormikProps<T>>;
}) {
const theme = useTheme();
return (
<Box
sx={{
mb: 2,
borderRadius: 2,
padding: 2,
backgroundColor: theme.palette.background.default,
boxShadow: '2'
}}
mt={2}
>
<Stack direction={'row'} spacing={1} alignItems={'center'}>
<SettingsIcon />
<Typography fontSize={22}>Tool options</Typography>
</Stack>
<Box mt={2}>
<Formik
innerRef={formRef}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={() => {}}
>
{(formikProps) => (
<ToolBody
compute={compute}
input={input}
getGroups={getGroups}
formikProps={formikProps}
>
{children}
</ToolBody>
)}
</Formik>
if (getGroups)
return (
<Box
sx={{
mb: 2,
borderRadius: 2,
padding: 2,
backgroundColor: theme.palette.background.default,
boxShadow: '2'
}}
mt={2}
>
<Stack direction={'row'} spacing={1} alignItems={'center'}>
<SettingsIcon />
<Typography fontSize={22}>Tool options</Typography>
</Stack>
<Box mt={2}>
<Formik
innerRef={formRef}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={() => {}}
>
{(formikProps) => (
<ToolBody
compute={compute}
input={input}
getGroups={getGroups}
formikProps={formikProps}
>
{children}
</ToolBody>
)}
</Formik>
</Box>
</Box>
</Box>
);
);
}

View File

@@ -1,3 +1,4 @@
import { tool as jsonPrettify } from './prettify/meta';
import { tool as jsonMinify } from './minify/meta';
export const jsonTools = [jsonPrettify];
export const jsonTools = [jsonPrettify, jsonMinify];

View File

@@ -0,0 +1,77 @@
import React, { useState } from 'react';
import ToolContent from '@components/ToolContent';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { minifyJson } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
type InitialValuesType = Record<string, never>;
const initialValues: InitialValuesType = {};
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Minify a Simple JSON Object',
description:
'This example shows how to minify a simple JSON object by removing all unnecessary whitespace.',
sampleText: `{
"name": "John Doe",
"age": 30,
"city": "New York"
}`,
sampleResult: `{"name":"John Doe","age":30,"city":"New York"}`,
sampleOptions: {}
},
{
title: 'Minify a Nested JSON Structure',
description:
'This example demonstrates minification of a complex nested JSON structure with arrays and objects.',
sampleText: `{
"users": [
{
"id": 1,
"name": "Alice",
"hobbies": ["reading", "gaming"]
},
{
"id": 2,
"name": "Bob",
"hobbies": ["swimming", "coding"]
}
]
}`,
sampleResult: `{"users":[{"id":1,"name":"Alice","hobbies":["reading","gaming"]},{"id":2,"name":"Bob","hobbies":["swimming","coding"]}]}`,
sampleOptions: {}
}
];
export default function MinifyJson({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (_: InitialValuesType, input: string) => {
if (input) setResult(minifyJson(input));
};
return (
<ToolContent
title={title}
inputComponent={
<ToolTextInput title="Input JSON" value={input} onChange={setInput} />
}
resultComponent={<ToolTextResult title="Minified JSON" value={result} />}
initialValues={initialValues}
getGroups={null}
toolInfo={{
title: 'What Is JSON Minification?',
description:
"JSON minification is the process of removing all unnecessary whitespace characters from JSON data while maintaining its validity. This includes removing spaces, newlines, and indentation that aren't required for the JSON to be parsed correctly. Minification reduces the size of JSON data, making it more efficient for storage and transmission while keeping the exact same data structure and values."
}}
exampleCards={exampleCards}
input={input}
setInput={setInput}
compute={compute}
/>
);
}

View File

@@ -0,0 +1,12 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('json', {
name: 'Minify JSON',
path: 'minify',
icon: 'lets-icons:json-light',
description: 'Minify your JSON by removing all unnecessary whitespace and formatting. This tool compresses JSON data to its smallest possible size while maintaining valid JSON structure.',
shortDescription: 'Remove all unnecessary whitespace from JSON data.',
keywords: ['minify', 'compress', 'minimize', 'json', 'compact'],
component: lazy(() => import('./index'))
});

View File

@@ -0,0 +1,10 @@
export const minifyJson = (text: string) => {
let parsedJson;
try {
parsedJson = JSON.parse(text);
} catch (e) {
throw new Error('Invalid JSON string');
}
return JSON.stringify(parsedJson);
};