feat: csv to json

This commit is contained in:
Ibrahima G. Coulibaly
2025-03-09 00:41:59 +00:00
parent 4e1d2468df
commit cf1c0e7e57
10 changed files with 984 additions and 104 deletions

1
.husky/pre-commit Normal file
View File

@@ -0,0 +1 @@
npx lint-staged

144
.idea/workspace.xml generated
View File

@@ -5,9 +5,16 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="feat: change pgn opacity"> <list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="feat: change pgn opacity">
<change afterPath="$PROJECT_DIR$/.husky/pre-commit" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/pages/tools/csv/csv-to-json/index.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/pages/tools/csv/csv-to-json/meta.ts" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/pages/tools/csv/csv-to-json/service.ts" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/pages/tools/csv/index.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" 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/tools/image/png/change-opacity/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/image/png/change-opacity/index.tsx" afterDir="false" /> <change beforePath="$PROJECT_DIR$/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/package-lock.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/image/png/change-opacity/service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/image/png/change-opacity/service.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/tools/defineTool.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/tools/defineTool.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/tools/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/tools/index.ts" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -30,16 +37,16 @@
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" /> <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
<option name="RESET_MODE" value="HARD" /> <option name="RESET_MODE" value="HARD" />
</component> </component>
<component name="GitHubPullRequestSearchHistory">{ <component name="GitHubPullRequestSearchHistory"><![CDATA[{
&quot;history&quot;: [ "history": [
{ {
&quot;assignee&quot;: &quot;iib0011&quot; "assignee": "iib0011"
} }
], ],
&quot;lastFilter&quot;: { "lastFilter": {
&quot;assignee&quot;: &quot;iib0011&quot; "assignee": "iib0011"
} }
}</component> }]]></component>
<component name="GitHubPullRequestState">{ <component name="GitHubPullRequestState">{
&quot;prStates&quot;: [ &quot;prStates&quot;: [
{ {
@@ -72,12 +79,12 @@
} }
] ]
}</component> }</component>
<component name="GithubPullRequestsUISettings">{ <component name="GithubPullRequestsUISettings"><![CDATA[{
&quot;selectedUrlAndAccountId&quot;: { "selectedUrlAndAccountId": {
&quot;url&quot;: &quot;https://github.com/iib0011/omni-tools.git&quot;, "url": "https://github.com/iib0011/omni-tools.git",
&quot;accountId&quot;: &quot;45f8cd51-000f-4ba4-a4c6-c4d96ac9b1e5&quot; "accountId": "45f8cd51-000f-4ba4-a4c6-c4d96ac9b1e5"
} }
}</component> }]]></component>
<component name="KubernetesApiProvider">{ <component name="KubernetesApiProvider">{
&quot;isMigrated&quot;: true &quot;isMigrated&quot;: true
}</component> }</component>
@@ -96,52 +103,52 @@
<option name="hideEmptyMiddlePackages" value="true" /> <option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" /> <option name="showLibraryContents" value="true" />
</component> </component>
<component name="PropertiesComponent">{ <component name="PropertiesComponent"><![CDATA[{
&quot;keyToString&quot;: { "keyToString": {
&quot;ASKED_ADD_EXTERNAL_FILES&quot;: &quot;true&quot;, "ASKED_ADD_EXTERNAL_FILES": "true",
&quot;ASKED_SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;, "ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
&quot;Docker.Dockerfile build.executor&quot;: &quot;Run&quot;, "Docker.Dockerfile build.executor": "Run",
&quot;Docker.Dockerfile.executor&quot;: &quot;Run&quot;, "Docker.Dockerfile.executor": "Run",
&quot;Playwright.JoinText Component.executor&quot;: &quot;Run&quot;, "Playwright.JoinText Component.executor": "Run",
&quot;Playwright.JoinText Component.should merge text pieces with specified join character.executor&quot;: &quot;Run&quot;, "Playwright.JoinText Component.should merge text pieces with specified join character.executor": "Run",
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;, "RunOnceActivity.OpenProjectViewOnStart": "true",
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;, "RunOnceActivity.ShowReadmeOnStart": "true",
&quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;, "RunOnceActivity.git.unshallow": "true",
&quot;Vitest.compute function (1).executor&quot;: &quot;Run&quot;, "Vitest.compute function (1).executor": "Run",
&quot;Vitest.compute function.executor&quot;: &quot;Run&quot;, "Vitest.compute function.executor": "Run",
&quot;Vitest.mergeText.executor&quot;: &quot;Run&quot;, "Vitest.mergeText.executor": "Run",
&quot;Vitest.mergeText.should merge lines and preserve blank lines when deleteBlankLines is false.executor&quot;: &quot;Run&quot;, "Vitest.mergeText.should merge lines and preserve blank lines when deleteBlankLines is false.executor": "Run",
&quot;Vitest.mergeText.should merge lines, preserve blank lines and trailing spaces when both deleteBlankLines and deleteTrailingSpaces are false.executor&quot;: &quot;Run&quot;, "Vitest.mergeText.should merge lines, preserve blank lines and trailing spaces when both deleteBlankLines and deleteTrailingSpaces are false.executor": "Run",
&quot;Vitest.removeDuplicateLines function.executor&quot;: &quot;Run&quot;, "Vitest.removeDuplicateLines function.executor": "Run",
&quot;Vitest.removeDuplicateLines function.newlines option.executor&quot;: &quot;Run&quot;, "Vitest.removeDuplicateLines function.newlines option.executor": "Run",
&quot;Vitest.removeDuplicateLines function.newlines option.should filter newlines when newlines is set to filter.executor&quot;: &quot;Run&quot;, "Vitest.removeDuplicateLines function.newlines option.should filter newlines when newlines is set to filter.executor": "Run",
&quot;Vitest.replaceText function.executor&quot;: &quot;Run&quot;, "Vitest.replaceText function.executor": "Run",
&quot;git-widget-placeholder&quot;: &quot;main&quot;, "git-widget-placeholder": "main",
&quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;, "ignore.virus.scanning.warn.message": "true",
&quot;kotlin-language-version-configured&quot;: &quot;true&quot;, "kotlin-language-version-configured": "true",
&quot;last_opened_file_path&quot;: &quot;C:/Users/Ibrahima/IdeaProjects/omni-tools/public/assets&quot;, "last_opened_file_path": "C:/Users/Ibrahima/IdeaProjects/omni-tools/.husky",
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;, "node.js.detected.package.eslint": "true",
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;, "node.js.detected.package.tslint": "true",
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;, "node.js.selected.package.eslint": "(autodetect)",
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;, "node.js.selected.package.tslint": "(autodetect)",
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;, "nodejs_package_manager_path": "npm",
&quot;npm.build.executor&quot;: &quot;Run&quot;, "npm.build.executor": "Run",
&quot;npm.dev.executor&quot;: &quot;Run&quot;, "npm.dev.executor": "Run",
&quot;npm.lint.executor&quot;: &quot;Run&quot;, "npm.lint.executor": "Run",
&quot;npm.prebuild.executor&quot;: &quot;Run&quot;, "npm.prebuild.executor": "Run",
&quot;npm.script:create:tool.executor&quot;: &quot;Run&quot;, "npm.script:create:tool.executor": "Run",
&quot;npm.test.executor&quot;: &quot;Run&quot;, "npm.test.executor": "Run",
&quot;npm.test:e2e.executor&quot;: &quot;Run&quot;, "npm.test:e2e.executor": "Run",
&quot;npm.test:e2e:run.executor&quot;: &quot;Run&quot;, "npm.test:e2e:run.executor": "Run",
&quot;prettierjs.PrettierConfiguration.Package&quot;: &quot;C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\prettier&quot;, "prettierjs.PrettierConfiguration.Package": "C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\prettier",
&quot;project.structure.last.edited&quot;: &quot;Problems&quot;, "project.structure.last.edited": "Problems",
&quot;project.structure.proportion&quot;: &quot;0.0&quot;, "project.structure.proportion": "0.0",
&quot;project.structure.side.proportion&quot;: &quot;0.2&quot;, "project.structure.side.proportion": "0.2",
&quot;settings.editor.selected.configurable&quot;: &quot;settings.typescriptcompiler&quot;, "settings.editor.selected.configurable": "settings.typescriptcompiler",
&quot;ts.external.directory.path&quot;: &quot;C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\typescript\\lib&quot;, "ts.external.directory.path": "C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\typescript\\lib",
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot; "vue.rearranger.settings.migration": "true"
} }
}</component> }]]></component>
<component name="ReactDesignerToolWindowState"> <component name="ReactDesignerToolWindowState">
<option name="myId2Visible"> <option name="myId2Visible">
<map> <map>
@@ -153,11 +160,11 @@
</component> </component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS"> <key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\.husky" />
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\public\assets" /> <recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\public\assets" />
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\src\assets" /> <recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\src\assets" />
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\.github" /> <recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\.github" />
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\components\options" /> <recent name="C:\Users\HP\IdeaProjects\omni-tools\src\components\options" />
<recent name="C:\Users\HP\IdeaProjects\omni-tools\src\assets" />
</key> </key>
<key name="MoveFile.RECENT_KEYS"> <key name="MoveFile.RECENT_KEYS">
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\public\assets" /> <recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\public\assets" />
@@ -329,14 +336,7 @@
<workItem from="1740880919391" duration="4395000" /> <workItem from="1740880919391" duration="4395000" />
<workItem from="1740923024259" duration="23000" /> <workItem from="1740923024259" duration="23000" />
<workItem from="1740933006573" duration="3679000" /> <workItem from="1740933006573" duration="3679000" />
</task> <workItem from="1741475969294" duration="4215000" />
<task id="LOCAL-00100" summary="refactor: optimize imports">
<option name="closed" value="true" />
<created>1720914702655</created>
<option name="number" value="00100" />
<option name="presentableId" value="LOCAL-00100" />
<option name="project" value="LOCAL" />
<updated>1720914702656</updated>
</task> </task>
<task id="LOCAL-00101" summary="chore: use string tools"> <task id="LOCAL-00101" summary="chore: use string tools">
<option name="closed" value="true" /> <option name="closed" value="true" />
@@ -722,7 +722,15 @@
<option name="project" value="LOCAL" /> <option name="project" value="LOCAL" />
<updated>1741423117739</updated> <updated>1741423117739</updated>
</task> </task>
<option name="localTasksCounter" value="149" /> <task id="LOCAL-00149" summary="feat: change pgn opacity">
<option name="closed" value="true" />
<created>1741423587662</created>
<option name="number" value="00149" />
<option name="presentableId" value="LOCAL-00149" />
<option name="project" value="LOCAL" />
<updated>1741423587662</updated>
</task>
<option name="localTasksCounter" value="150" />
<servers /> <servers />
</component> </component>
<component name="TypeScriptGeneratedFilesManager"> <component name="TypeScriptGeneratedFilesManager">

593
package-lock.json generated
View File

@@ -21,6 +21,7 @@
"color": "^4.2.3", "color": "^4.2.3",
"formik": "^2.4.6", "formik": "^2.4.6",
"jimp": "^0.22.12", "jimp": "^0.22.12",
"lint-staged": "^15.4.3",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"morsee": "^1.0.9", "morsee": "^1.0.9",
"notistack": "^3.0.1", "notistack": "^3.0.1",
@@ -3468,6 +3469,21 @@
"url": "https://github.com/sponsors/epoberezkin" "url": "https://github.com/sponsors/epoberezkin"
} }
}, },
"node_modules/ansi-escapes": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz",
"integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==",
"license": "MIT",
"dependencies": {
"environment": "^1.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/ansi-regex": { "node_modules/ansi-regex": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
@@ -3864,7 +3880,6 @@
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"dependencies": { "dependencies": {
"fill-range": "^7.1.1" "fill-range": "^7.1.1"
}, },
@@ -4097,6 +4112,87 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/cli-cursor": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
"integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==",
"license": "MIT",
"dependencies": {
"restore-cursor": "^5.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/cli-truncate": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz",
"integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==",
"license": "MIT",
"dependencies": {
"slice-ansi": "^5.0.0",
"string-width": "^7.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/cli-truncate/node_modules/ansi-regex": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/cli-truncate/node_modules/emoji-regex": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
"integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
"license": "MIT"
},
"node_modules/cli-truncate/node_modules/string-width": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
"integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
"license": "MIT",
"dependencies": {
"emoji-regex": "^10.3.0",
"get-east-asian-width": "^1.0.0",
"strip-ansi": "^7.1.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/cli-truncate/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/cliui": { "node_modules/cliui": {
"version": "8.0.1", "version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
@@ -4193,6 +4289,12 @@
"simple-swizzle": "^0.2.2" "simple-swizzle": "^0.2.2"
} }
}, },
"node_modules/colorette": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
"license": "MIT"
},
"node_modules/combined-stream": { "node_modules/combined-stream": {
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -4310,7 +4412,6 @@
"version": "7.0.3", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dev": true,
"dependencies": { "dependencies": {
"path-key": "^3.1.0", "path-key": "^3.1.0",
"shebang-command": "^2.0.0", "shebang-command": "^2.0.0",
@@ -4654,6 +4755,18 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/environment": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz",
"integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/error-ex": { "node_modules/error-ex": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -5247,11 +5360,16 @@
"through": "~2.3.1" "through": "~2.3.1"
} }
}, },
"node_modules/eventemitter3": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
"license": "MIT"
},
"node_modules/execa": { "node_modules/execa": {
"version": "8.0.1", "version": "8.0.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
"integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
"dev": true,
"dependencies": { "dependencies": {
"cross-spawn": "^7.0.3", "cross-spawn": "^7.0.3",
"get-stream": "^8.0.1", "get-stream": "^8.0.1",
@@ -5374,7 +5492,6 @@
"version": "7.1.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"dependencies": { "dependencies": {
"to-regex-range": "^5.0.1" "to-regex-range": "^5.0.1"
}, },
@@ -5589,6 +5706,18 @@
"node": "6.* || 8.* || >= 10.*" "node": "6.* || 8.* || >= 10.*"
} }
}, },
"node_modules/get-east-asian-width": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz",
"integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/get-func-name": { "node_modules/get-func-name": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
@@ -5621,7 +5750,6 @@
"version": "8.0.1", "version": "8.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
"integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
"dev": true,
"engines": { "engines": {
"node": ">=16" "node": ">=16"
}, },
@@ -5959,7 +6087,6 @@
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
"integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
"dev": true,
"engines": { "engines": {
"node": ">=16.17.0" "node": ">=16.17.0"
} }
@@ -6351,7 +6478,6 @@
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"engines": { "engines": {
"node": ">=0.12.0" "node": ">=0.12.0"
} }
@@ -6436,7 +6562,6 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
"dev": true,
"engines": { "engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0" "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}, },
@@ -6550,8 +6675,7 @@
"node_modules/isexe": { "node_modules/isexe": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
"dev": true
}, },
"node_modules/isomorphic-fetch": { "node_modules/isomorphic-fetch": {
"version": "3.0.0", "version": "3.0.0",
@@ -6790,6 +6914,185 @@
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
}, },
"node_modules/lint-staged": {
"version": "15.4.3",
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.4.3.tgz",
"integrity": "sha512-FoH1vOeouNh1pw+90S+cnuoFwRfUD9ijY2GKy5h7HS3OR7JVir2N2xrsa0+Twc1B7cW72L+88geG5cW4wIhn7g==",
"license": "MIT",
"dependencies": {
"chalk": "^5.4.1",
"commander": "^13.1.0",
"debug": "^4.4.0",
"execa": "^8.0.1",
"lilconfig": "^3.1.3",
"listr2": "^8.2.5",
"micromatch": "^4.0.8",
"pidtree": "^0.6.0",
"string-argv": "^0.3.2",
"yaml": "^2.7.0"
},
"bin": {
"lint-staged": "bin/lint-staged.js"
},
"engines": {
"node": ">=18.12.0"
},
"funding": {
"url": "https://opencollective.com/lint-staged"
}
},
"node_modules/lint-staged/node_modules/chalk": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
"integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
"license": "MIT",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/lint-staged/node_modules/commander": {
"version": "13.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz",
"integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/lint-staged/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/lint-staged/node_modules/lilconfig": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
"integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
"license": "MIT",
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antonk52"
}
},
"node_modules/lint-staged/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/listr2": {
"version": "8.2.5",
"resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz",
"integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==",
"license": "MIT",
"dependencies": {
"cli-truncate": "^4.0.0",
"colorette": "^2.0.20",
"eventemitter3": "^5.0.1",
"log-update": "^6.1.0",
"rfdc": "^1.4.1",
"wrap-ansi": "^9.0.0"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/listr2/node_modules/ansi-regex": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/listr2/node_modules/ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/listr2/node_modules/emoji-regex": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
"integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
"license": "MIT"
},
"node_modules/listr2/node_modules/string-width": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
"integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
"license": "MIT",
"dependencies": {
"emoji-regex": "^10.3.0",
"get-east-asian-width": "^1.0.0",
"strip-ansi": "^7.1.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/listr2/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/listr2/node_modules/wrap-ansi": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
"integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.2.1",
"string-width": "^7.0.0",
"strip-ansi": "^7.1.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/load-bmfont": { "node_modules/load-bmfont": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz",
@@ -6900,6 +7203,135 @@
"integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==",
"dev": true "dev": true
}, },
"node_modules/log-update": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz",
"integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==",
"license": "MIT",
"dependencies": {
"ansi-escapes": "^7.0.0",
"cli-cursor": "^5.0.0",
"slice-ansi": "^7.1.0",
"strip-ansi": "^7.1.0",
"wrap-ansi": "^9.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/log-update/node_modules/ansi-regex": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/log-update/node_modules/ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/log-update/node_modules/emoji-regex": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
"integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
"license": "MIT"
},
"node_modules/log-update/node_modules/is-fullwidth-code-point": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz",
"integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==",
"license": "MIT",
"dependencies": {
"get-east-asian-width": "^1.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/log-update/node_modules/slice-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz",
"integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.2.1",
"is-fullwidth-code-point": "^5.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
}
},
"node_modules/log-update/node_modules/string-width": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
"integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
"license": "MIT",
"dependencies": {
"emoji-regex": "^10.3.0",
"get-east-asian-width": "^1.0.0",
"strip-ansi": "^7.1.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/log-update/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/log-update/node_modules/wrap-ansi": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
"integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.2.1",
"string-width": "^7.0.0",
"strip-ansi": "^7.1.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/loose-envify": { "node_modules/loose-envify": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -6968,8 +7400,7 @@
"node_modules/merge-stream": { "node_modules/merge-stream": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
"dev": true
}, },
"node_modules/merge2": { "node_modules/merge2": {
"version": "1.4.1", "version": "1.4.1",
@@ -6981,10 +7412,10 @@
} }
}, },
"node_modules/micromatch": { "node_modules/micromatch": {
"version": "4.0.7", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true, "license": "MIT",
"dependencies": { "dependencies": {
"braces": "^3.0.3", "braces": "^3.0.3",
"picomatch": "^2.3.1" "picomatch": "^2.3.1"
@@ -7029,7 +7460,6 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
"dev": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@@ -7037,6 +7467,18 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/mimic-function": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
"integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/min-document": { "node_modules/min-document": {
"version": "2.19.0", "version": "2.19.0",
"resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
@@ -7229,7 +7671,6 @@
"version": "5.3.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
"integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
"dev": true,
"dependencies": { "dependencies": {
"path-key": "^4.0.0" "path-key": "^4.0.0"
}, },
@@ -7244,7 +7685,6 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
"dev": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@@ -7405,7 +7845,6 @@
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
"dev": true,
"dependencies": { "dependencies": {
"mimic-fn": "^4.0.0" "mimic-fn": "^4.0.0"
}, },
@@ -7549,7 +7988,6 @@
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -7634,7 +8072,6 @@
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": { "engines": {
"node": ">=8.6" "node": ">=8.6"
}, },
@@ -7642,6 +8079,18 @@
"url": "https://github.com/sponsors/jonschlinkert" "url": "https://github.com/sponsors/jonschlinkert"
} }
}, },
"node_modules/pidtree": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
"integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
"license": "MIT",
"bin": {
"pidtree": "bin/pidtree.js"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/pify": { "node_modules/pify": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
@@ -8310,6 +8759,37 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/restore-cursor": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz",
"integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==",
"license": "MIT",
"dependencies": {
"onetime": "^7.0.0",
"signal-exit": "^4.1.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/restore-cursor/node_modules/onetime": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
"integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
"license": "MIT",
"dependencies": {
"mimic-function": "^5.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/reusify": { "node_modules/reusify": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
@@ -8320,6 +8800,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/rfdc": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
"license": "MIT"
},
"node_modules/rimraf": { "node_modules/rimraf": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -8524,7 +9010,6 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"dependencies": { "dependencies": {
"shebang-regex": "^3.0.0" "shebang-regex": "^3.0.0"
}, },
@@ -8536,7 +9021,6 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -8569,7 +9053,6 @@
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
"engines": { "engines": {
"node": ">=14" "node": ">=14"
}, },
@@ -8613,6 +9096,46 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/slice-ansi": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
"integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.0.0",
"is-fullwidth-code-point": "^4.0.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
}
},
"node_modules/slice-ansi/node_modules/ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
"integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/source-map": { "node_modules/source-map": {
"version": "0.5.7", "version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -8823,6 +9346,15 @@
"safe-buffer": "~5.2.0" "safe-buffer": "~5.2.0"
} }
}, },
"node_modules/string-argv": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
"integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
"license": "MIT",
"engines": {
"node": ">=0.6.19"
}
},
"node_modules/string-width": { "node_modules/string-width": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
@@ -8992,7 +9524,6 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
"integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
"dev": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@@ -9317,7 +9848,6 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"dependencies": { "dependencies": {
"is-number": "^7.0.0" "is-number": "^7.0.0"
}, },
@@ -9853,7 +10383,6 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"dependencies": { "dependencies": {
"isexe": "^2.0.0" "isexe": "^2.0.0"
}, },
@@ -10122,10 +10651,10 @@
} }
}, },
"node_modules/yaml": { "node_modules/yaml": {
"version": "2.4.5", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz",
"integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==",
"dev": true, "license": "ISC",
"bin": { "bin": {
"yaml": "bin.mjs" "yaml": "bin.mjs"
}, },

View File

@@ -38,6 +38,7 @@
"color": "^4.2.3", "color": "^4.2.3",
"formik": "^2.4.6", "formik": "^2.4.6",
"jimp": "^0.22.12", "jimp": "^0.22.12",
"lint-staged": "^15.4.3",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"morsee": "^1.0.9", "morsee": "^1.0.9",
"notistack": "^3.0.1", "notistack": "^3.0.1",
@@ -83,5 +84,8 @@
"vite": "^5.2.11", "vite": "^5.2.11",
"vite-tsconfig-paths": "^4.3.2", "vite-tsconfig-paths": "^4.3.2",
"vitest": "^1.6.0" "vitest": "^1.6.0"
},
"lint-staged": {
"*.{ts,tsx,js,jsx,json}": "prettier --write"
} }
} }

View File

@@ -0,0 +1,210 @@
import React, { useState } from 'react';
import ToolContent from '@components/ToolContent';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { convertCsvToJson } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import { Box } from '@mui/material';
import RadioWithTextField from '@components/options/RadioWithTextField';
import SimpleRadio from '@components/options/SimpleRadio';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
type InitialValuesType = {
delimiter: string;
quote: string;
comment: string;
useHeaders: boolean;
skipEmptyLines: boolean;
dynamicTypes: boolean;
indentationType: 'tab' | 'space';
spacesCount: number;
};
const initialValues: InitialValuesType = {
delimiter: ',',
quote: '"',
comment: '#',
useHeaders: true,
skipEmptyLines: true,
dynamicTypes: true,
indentationType: 'space',
spacesCount: 2
};
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Basic CSV to JSON Array',
description: 'Convert a simple CSV file into a JSON array structure.',
sampleText: 'name,age,city\nJohn,30,New York\nAlice,25,London',
sampleResult: `[
{
"name": "John",
"age": 30,
"city": "New York"
},
{
"name": "Alice",
"age": 25,
"city": "London"
}
]`,
sampleOptions: {
...initialValues,
useHeaders: true,
dynamicTypes: true
}
},
{
title: 'CSV with Custom Delimiter',
description: 'Convert a CSV file that uses semicolons as separators.',
sampleText: 'product;price;quantity\nApple;1.99;50\nBanana;0.99;100',
sampleResult: `[
{
"product": "Apple",
"price": 1.99,
"quantity": 50
},
{
"product": "Banana",
"price": 0.99,
"quantity": 100
}
]`,
sampleOptions: {
...initialValues,
delimiter: ';'
}
},
{
title: 'CSV with Comments and Empty Lines',
description: 'Process CSV data while handling comments and empty lines.',
sampleText: `# This is a comment
id,name,active
1,John,true
# Another comment
2,Jane,false
3,Bob,true`,
sampleResult: `[
{
"id": 1,
"name": "John",
"active": true
},
{
"id": 2,
"name": "Jane",
"active": false
},
{
"id": 3,
"name": "Bob",
"active": true
}
]`,
sampleOptions: {
...initialValues,
skipEmptyLines: true,
comment: '#'
}
}
];
export default function CsvToJson({ title }: ToolComponentProps) {
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (values: InitialValuesType, input: string) => {
if (input) {
try {
const jsonResult = convertCsvToJson(input, {
delimiter: values.delimiter,
quote: values.quote,
comment: values.comment,
useHeaders: values.useHeaders,
skipEmptyLines: values.skipEmptyLines,
dynamicTypes: values.dynamicTypes
});
setResult(jsonResult);
} catch (error) {
setResult(
`Error: ${
error instanceof Error ? error.message : 'Invalid CSV format'
}`
);
}
}
};
return (
<ToolContent
title={title}
input={input}
setInput={setInput}
initialValues={initialValues}
compute={compute}
exampleCards={exampleCards}
inputComponent={
<ToolTextInput title="Input CSV" value={input} onChange={setInput} />
}
resultComponent={<ToolTextResult title="Output JSON" value={result} />}
getGroups={({ values, updateField }) => [
{
title: 'Input CSV Format',
component: (
<Box>
<TextFieldWithDesc
description="Column Separator"
value={values.delimiter}
onOwnChange={(val) => updateField('delimiter', val)}
/>
<TextFieldWithDesc
description="Field Quote"
onOwnChange={(val) => updateField('quote', val)}
value={values.quote}
/>
<TextFieldWithDesc
description="Comment Symbol"
value={values.comment}
onOwnChange={(val) => updateField('comment', val)}
/>
</Box>
)
},
{
title: 'Conversion Options',
component: (
<Box>
<CheckboxWithDesc
checked={values.useHeaders}
onChange={(value) => updateField('useHeaders', value)}
title="Use Headers"
description="First row is treated as column headers"
/>
<CheckboxWithDesc
checked={values.skipEmptyLines}
onChange={(value) => updateField('skipEmptyLines', value)}
title="Skip Empty Lines"
description="Don't process empty lines in the CSV"
/>
<CheckboxWithDesc
checked={values.dynamicTypes}
onChange={(value) => updateField('dynamicTypes', value)}
title="Dynamic Types"
description="Convert numbers and booleans to their proper types"
/>
</Box>
)
}
]}
toolInfo={{
title: 'What Is a CSV to JSON Converter?',
description:
'This tool transforms Comma Separated Values (CSV) files to JavaScript Object Notation (JSON) data structures. It supports various CSV formats with customizable delimiters, quote characters, and comment symbols. The converter can treat the first row as headers, skip empty lines, and automatically detect data types like numbers and booleans. The resulting JSON can be used for data migration, backups, or as input for other applications.'
}}
/>
);
}

View File

@@ -0,0 +1,13 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('csv', {
name: 'Convert CSV to JSON',
path: 'csv-to-json',
icon: 'lets-icons:json-light',
description:
'Convert CSV files to JSON format with customizable options for delimiters, quotes, and output formatting. Support for headers, comments, and dynamic type conversion.',
shortDescription: 'Convert CSV data to JSON format',
keywords: ['csv', 'json', 'convert', 'transform', 'parse'],
component: lazy(() => import('./index'))
});

View File

@@ -0,0 +1,103 @@
type CsvToJsonOptions = {
delimiter: string;
quote: string;
comment: string;
useHeaders: boolean;
skipEmptyLines: boolean;
dynamicTypes: boolean;
};
const defaultOptions: CsvToJsonOptions = {
delimiter: ',',
quote: '"',
comment: '#',
useHeaders: true,
skipEmptyLines: true,
dynamicTypes: true
};
export const convertCsvToJson = (
csv: string,
options: Partial<CsvToJsonOptions> = {}
): string => {
const opts = { ...defaultOptions, ...options };
const lines = csv.split('\n');
const result: any[] = [];
let headers: string[] = [];
// Filter out comments and empty lines
const validLines = lines.filter((line) => {
const trimmedLine = line.trim();
return (
trimmedLine &&
(!opts.skipEmptyLines ||
!containsOnlyCustomCharAndSpaces(trimmedLine, opts.delimiter)) &&
!trimmedLine.startsWith(opts.comment)
);
});
if (validLines.length === 0) {
return '[]';
}
// Parse headers if enabled
if (opts.useHeaders) {
headers = parseCsvLine(validLines[0], opts);
validLines.shift();
}
// Parse data lines
for (const line of validLines) {
const values = parseCsvLine(line, opts);
if (opts.useHeaders) {
const obj: Record<string, any> = {};
headers.forEach((header, i) => {
obj[header] = parseValue(values[i], opts.dynamicTypes);
});
result.push(obj);
} else {
result.push(values.map((v) => parseValue(v, opts.dynamicTypes)));
}
}
return JSON.stringify(result, null, 2);
};
const parseCsvLine = (line: string, options: CsvToJsonOptions): string[] => {
const values: string[] = [];
let currentValue = '';
let inQuotes = false;
for (let i = 0; i < line.length; i++) {
const char = line[i];
if (char === options.quote) {
inQuotes = !inQuotes;
} else if (char === options.delimiter && !inQuotes) {
values.push(currentValue.trim());
currentValue = '';
} else {
currentValue += char;
}
}
values.push(currentValue.trim());
return values;
};
const parseValue = (value: string, dynamicTypes: boolean): any => {
if (!dynamicTypes) return value;
if (value.toLowerCase() === 'true') return true;
if (value.toLowerCase() === 'false') return false;
if (value === 'null') return null;
if (!isNaN(Number(value))) return Number(value);
return value;
};
function containsOnlyCustomCharAndSpaces(str: string, customChar: string) {
const regex = new RegExp(`^[${customChar}\\s]*$`);
return regex.test(str);
}

View File

@@ -0,0 +1,3 @@
import { tool as csvToJson } from './csv-to-json/meta';
export const csvTools = [csvToJson];

View File

@@ -18,7 +18,8 @@ export type ToolCategory =
| 'number' | 'number'
| 'gif' | 'gif'
| 'list' | 'list'
| 'json'; | 'json'
| 'csv';
export interface DefinedTool { export interface DefinedTool {
type: ToolCategory; type: ToolCategory;

View File

@@ -7,6 +7,7 @@ import { videoTools } from '../pages/tools/video';
import { listTools } from '../pages/tools/list'; import { listTools } from '../pages/tools/list';
import { Entries } from 'type-fest'; import { Entries } from 'type-fest';
import { jsonTools } from '../pages/tools/json'; import { jsonTools } from '../pages/tools/json';
import { csvTools } from '../pages/tools/csv';
import { IconifyIcon } from '@iconify/react'; import { IconifyIcon } from '@iconify/react';
export const tools: DefinedTool[] = [ export const tools: DefinedTool[] = [
@@ -14,6 +15,7 @@ export const tools: DefinedTool[] = [
...stringTools, ...stringTools,
...jsonTools, ...jsonTools,
...listTools, ...listTools,
...csvTools,
...videoTools, ...videoTools,
...numberTools ...numberTools
]; ];
@@ -59,6 +61,12 @@ const categoriesConfig: {
icon: 'lets-icons:json-light', icon: 'lets-icons:json-light',
value: value:
'Tools for working with JSON data structures prettify and minify JSON objects, flatten JSON arrays, stringify JSON values, analyze data, and much more' 'Tools for working with JSON data structures prettify and minify JSON objects, flatten JSON arrays, stringify JSON values, analyze data, and much more'
},
{
type: 'csv',
icon: 'material-symbols-light:csv-outline',
value:
'Tools for working with CSV files - convert CSV to different formats, manipulate CSV data, validate CSV structure, and process CSV files efficiently.'
} }
]; ];
export const filterTools = ( export const filterTools = (