diff --git a/.gitignore b/.gitignore
index 6bf6273..cf40755 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,8 +32,8 @@ yarn-error.log*
.vercel
# typescript
-*.tsbuildinfo
next-env.d.ts
+*.tsbuildinfo
.yalc
yalc
yalc.lock
\ No newline at end of file
diff --git a/declare.d.ts b/declare.d.ts
new file mode 100644
index 0000000..9aa7166
--- /dev/null
+++ b/declare.d.ts
@@ -0,0 +1 @@
+declare module 'css2less';
diff --git a/package-lock.json b/package-lock.json
index fb67145..8c1eeed 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -31,12 +31,16 @@
"change-case": "^5.3.0",
"compressorjs": "^1.2.1",
"crypto-js": "^4.2.0",
+ "css2less": "^0.1.4",
+ "dompurify": "^3.0.6",
"eslint-config-next": "^14.0.4",
"html-entities": "^2.4.0",
"ip": "^1.1.8",
"js-yaml": "^4.1.0",
"jsfuck": "^0.4.0",
"json-2-csv": "^5.0.1",
+ "less": "^4.2.0",
+ "marked": "^11.1.1",
"next": "^14.0.4",
"next-compose-plugins": "^2.2.1",
"next-transpile-modules": "^10.0.1",
@@ -64,8 +68,11 @@
"sql-formatter": "^15.0.2",
"sql.js": "^1.9.0",
"swiper": "^8.4.7",
+ "tesseract.js": "^5.0.4",
+ "turndown": "^7.1.2",
"typescript": "5.0.4",
"xlsx": "^0.18.5",
+ "xml2js": "^0.6.2",
"xmorse": "^1.0.0",
"yarn": "^1.22.21"
},
@@ -74,7 +81,9 @@
"@commitlint/config-conventional": "^18.4.3",
"@types/big-integer": "^0.0.31",
"@types/crypto-js": "^4.2.0",
+ "@types/dompurify": "^3.0.5",
"@types/ip": "^1.1.3",
+ "@types/less": "^3.0.6",
"@types/node": "20.1.5",
"@types/node-forge": "^1.3.10",
"@types/qs": "^6.9.7",
@@ -83,6 +92,8 @@
"@types/react-dom": "18.2.4",
"@types/react-syntax-highlighter": "^15.5.11",
"@types/sql.js": "^1.4.9",
+ "@types/turndown": "^5.0.4",
+ "@types/xml2js": "^0.4.14",
"@typescript-eslint/eslint-plugin": "^6.15.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
@@ -1737,21 +1748,6 @@
"glob": "7.1.7"
}
},
- "node_modules/@next/swc-darwin-arm64": {
- "version": "14.0.4",
- "resolved": "https://registry.npmmirror.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz",
- "integrity": "sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/@next/swc-darwin-x64": {
"version": "14.0.4",
"resolved": "https://registry.npmmirror.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz",
@@ -1767,111 +1763,6 @@
"node": ">= 10"
}
},
- "node_modules/@next/swc-linux-arm64-gnu": {
- "version": "14.0.4",
- "resolved": "https://registry.npmmirror.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz",
- "integrity": "sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-linux-arm64-musl": {
- "version": "14.0.4",
- "resolved": "https://registry.npmmirror.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz",
- "integrity": "sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-linux-x64-gnu": {
- "version": "14.0.4",
- "resolved": "https://registry.npmmirror.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz",
- "integrity": "sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-linux-x64-musl": {
- "version": "14.0.4",
- "resolved": "https://registry.npmmirror.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz",
- "integrity": "sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-win32-arm64-msvc": {
- "version": "14.0.4",
- "resolved": "https://registry.npmmirror.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz",
- "integrity": "sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==",
- "cpu": [
- "arm64"
- ],
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-win32-ia32-msvc": {
- "version": "14.0.4",
- "resolved": "https://registry.npmmirror.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz",
- "integrity": "sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==",
- "cpu": [
- "ia32"
- ],
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@next/swc-win32-x64-msvc": {
- "version": "14.0.4",
- "resolved": "https://registry.npmmirror.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz",
- "integrity": "sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==",
- "cpu": [
- "x64"
- ],
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -2011,6 +1902,15 @@
"@types/ms": "*"
}
},
+ "node_modules/@types/dompurify": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmmirror.com/@types/dompurify/-/dompurify-3.0.5.tgz",
+ "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==",
+ "dev": true,
+ "dependencies": {
+ "@types/trusted-types": "*"
+ }
+ },
"node_modules/@types/emscripten": {
"version": "1.39.10",
"resolved": "https://registry.npmmirror.com/@types/emscripten/-/emscripten-1.39.10.tgz",
@@ -2055,6 +1955,12 @@
"resolved": "https://registry.npmmirror.com/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
},
+ "node_modules/@types/less": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmmirror.com/@types/less/-/less-3.0.6.tgz",
+ "integrity": "sha512-PecSzorDGdabF57OBeQO/xFbAkYWo88g4Xvnsx7LRwqLC17I7OoKtA3bQB9uXkY6UkMWCOsA8HSVpaoitscdXw==",
+ "dev": true
+ },
"node_modules/@types/mdast": {
"version": "3.0.15",
"resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-3.0.15.tgz",
@@ -2193,11 +2099,32 @@
"@types/node": "*"
}
},
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
+ "dev": true
+ },
+ "node_modules/@types/turndown": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmmirror.com/@types/turndown/-/turndown-5.0.4.tgz",
+ "integrity": "sha512-28GI33lCCkU4SGH1GvjDhFgOVr+Tym4PXGBIU1buJUa6xQolniPArtUT+kv42RR2N9MsMLInkr904Aq+ESHBJg==",
+ "dev": true
+ },
"node_modules/@types/unist": {
"version": "2.0.10",
"resolved": "https://registry.npmmirror.com/@types/unist/-/unist-2.0.10.tgz",
"integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA=="
},
+ "node_modules/@types/xml2js": {
+ "version": "0.4.14",
+ "resolved": "https://registry.npmmirror.com/@types/xml2js/-/xml2js-0.4.14.tgz",
+ "integrity": "sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "6.15.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.15.0.tgz",
@@ -2726,6 +2653,11 @@
"resolved": "https://registry.npmmirror.com/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.29.0.tgz",
"integrity": "sha512-0pcSSGxC0QxT+yVkivxIqW0Y4VlO2XSDPofBAqoJ1qJxgH9eiUDLv50Rixij2cDuEfx4M6DpD9UGZpRhT5Q8qg=="
},
+ "node_modules/bmp-js": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmmirror.com/bmp-js/-/bmp-js-0.1.0.tgz",
+ "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw=="
+ },
"node_modules/bplist-parser": {
"version": "0.2.0",
"resolved": "https://registry.npmmirror.com/bplist-parser/-/bplist-parser-0.2.0.tgz",
@@ -3130,6 +3062,14 @@
"resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
},
+ "node_modules/copy-anything": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-2.0.6.tgz",
+ "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==",
+ "dependencies": {
+ "is-what": "^3.14.1"
+ }
+ },
"node_modules/copy-to-clipboard": {
"version": "3.3.3",
"resolved": "https://registry.npmmirror.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
@@ -3211,6 +3151,11 @@
"postcss-value-parser": "^3.3.0"
}
},
+ "node_modules/css2less": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmmirror.com/css2less/-/css2less-0.1.4.tgz",
+ "integrity": "sha512-3fvKdQGpMc+NuFxgYyQHM/HbtVydXXTAt1FH7yihYoWq52ydPwfTF5W5OU/zTx2rNZ4L9Nj4qrlWshsLS4Z3fg=="
+ },
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
@@ -3452,6 +3397,16 @@
"ssr-window": "^4.0.0"
}
},
+ "node_modules/domino": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmmirror.com/domino/-/domino-2.1.6.tgz",
+ "integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ=="
+ },
+ "node_modules/dompurify": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.0.6.tgz",
+ "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w=="
+ },
"node_modules/dot-prop": {
"version": "5.3.0",
"resolved": "https://registry.npmmirror.com/dot-prop/-/dot-prop-5.3.0.tgz",
@@ -3522,6 +3477,18 @@
"node": ">=10.13.0"
}
},
+ "node_modules/errno": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz",
+ "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
+ "optional": true,
+ "dependencies": {
+ "prr": "~1.0.1"
+ },
+ "bin": {
+ "errno": "cli.js"
+ }
+ },
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.2.tgz",
@@ -4866,6 +4833,23 @@
"node": ">=14"
}
},
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "optional": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/idb-keyval": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmmirror.com/idb-keyval/-/idb-keyval-6.2.1.tgz",
+ "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg=="
+ },
"node_modules/ignore": {
"version": "5.3.0",
"resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.3.0.tgz",
@@ -4880,6 +4864,18 @@
"integrity": "sha512-+F8B0ip7w6DskaN3bd3GyTvlPMiBfd3kom3qo+k/1jFNkIqtIUqrD0t7r97qHaBtDkTp/vp1DLAU3lqyj0szFA==",
"peer": true
},
+ "node_modules/image-size": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmmirror.com/image-size/-/image-size-0.5.5.tgz",
+ "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==",
+ "optional": true,
+ "bin": {
+ "image-size": "bin/image-size.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -5077,6 +5073,11 @@
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
+ "node_modules/is-electron": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmmirror.com/is-electron/-/is-electron-2.2.2.tgz",
+ "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg=="
+ },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -5280,6 +5281,11 @@
"node": ">= 0.4"
}
},
+ "node_modules/is-url": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmmirror.com/is-url/-/is-url-1.2.4.tgz",
+ "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="
+ },
"node_modules/is-weakmap": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/is-weakmap/-/is-weakmap-2.0.1.tgz",
@@ -5302,6 +5308,11 @@
"get-intrinsic": "^1.1.1"
}
},
+ "node_modules/is-what": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmmirror.com/is-what/-/is-what-3.14.1.tgz",
+ "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA=="
+ },
"node_modules/is-wsl": {
"version": "2.2.0",
"resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz",
@@ -5539,6 +5550,40 @@
"node": ">=0.10"
}
},
+ "node_modules/less": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmmirror.com/less/-/less-4.2.0.tgz",
+ "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==",
+ "dependencies": {
+ "copy-anything": "^2.0.1",
+ "parse-node-version": "^1.0.1",
+ "tslib": "^2.3.0"
+ },
+ "bin": {
+ "lessc": "bin/lessc"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "optionalDependencies": {
+ "errno": "^0.1.1",
+ "graceful-fs": "^4.1.2",
+ "image-size": "~0.5.0",
+ "make-dir": "^2.1.0",
+ "mime": "^1.4.1",
+ "needle": "^3.1.0",
+ "source-map": "~0.6.0"
+ }
+ },
+ "node_modules/less/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "optional": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/levn": {
"version": "0.4.1",
"resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz",
@@ -5863,6 +5908,28 @@
"node": ">=10"
}
},
+ "node_modules/make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "optional": true,
+ "dependencies": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "optional": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
"node_modules/map-obj": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/map-obj/-/map-obj-4.3.0.tgz",
@@ -5877,6 +5944,17 @@
"resolved": "https://registry.npmmirror.com/markdown-table/-/markdown-table-3.0.3.tgz",
"integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw=="
},
+ "node_modules/marked": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmmirror.com/marked/-/marked-11.1.1.tgz",
+ "integrity": "sha512-EgxRjgK9axsQuUa/oKMx5DEY8oXpKJfk61rT5iY3aRlgU6QJtUcxU5OAymdhCvWvhYcd9FKmO5eQoX8m9VGJXg==",
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
"node_modules/mdast-util-definitions": {
"version": "5.1.2",
"resolved": "https://registry.npmmirror.com/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz",
@@ -6387,6 +6465,18 @@
"node": ">=8.6"
}
},
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "optional": true,
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
@@ -6528,6 +6618,22 @@
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
+ "node_modules/needle": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmmirror.com/needle/-/needle-3.3.1.tgz",
+ "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==",
+ "optional": true,
+ "dependencies": {
+ "iconv-lite": "^0.6.3",
+ "sax": "^1.2.4"
+ },
+ "bin": {
+ "needle": "bin/needle"
+ },
+ "engines": {
+ "node": ">= 4.4.x"
+ }
+ },
"node_modules/next": {
"version": "14.0.4",
"resolved": "https://registry.npmmirror.com/next/-/next-14.0.4.tgz",
@@ -6587,6 +6693,25 @@
"enhanced-resolve": "^5.10.0"
}
},
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
"node_modules/node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmmirror.com/node-forge/-/node-forge-1.3.1.tgz",
@@ -6766,6 +6891,14 @@
"node": ">=14.16"
}
},
+ "node_modules/opencollective-postinstall": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmmirror.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
+ "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
+ "bin": {
+ "opencollective-postinstall": "index.js"
+ }
+ },
"node_modules/optionator": {
"version": "0.9.3",
"resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.3.tgz",
@@ -6856,6 +6989,14 @@
"node": ">=8"
}
},
+ "node_modules/parse-node-version": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz",
+ "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
@@ -6918,6 +7059,15 @@
"node": ">=0.10"
}
},
+ "node_modules/pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmmirror.com/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "optional": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/popmotion": {
"version": "9.3.6",
"resolved": "https://registry.npmmirror.com/popmotion/-/popmotion-9.3.6.tgz",
@@ -7016,6 +7166,12 @@
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
+ "node_modules/prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz",
+ "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==",
+ "optional": true
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
@@ -7922,6 +8078,17 @@
"is-regex": "^1.1.4"
}
},
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "optional": true
+ },
+ "node_modules/sax": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmmirror.com/sax/-/sax-1.3.0.tgz",
+ "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA=="
+ },
"node_modules/scheduler": {
"version": "0.23.0",
"resolved": "https://registry.npmmirror.com/scheduler/-/scheduler-0.23.0.tgz",
@@ -8498,6 +8665,34 @@
"node": ">=6"
}
},
+ "node_modules/tesseract.js": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmmirror.com/tesseract.js/-/tesseract.js-5.0.4.tgz",
+ "integrity": "sha512-GCIoSQMZlvTP2AaHrjUOH29/oyO7ZyHVe+BhTexEcO7/nDClRVDRjl2sYJLOWSSNbTDrm5q2m1+gfaf3lUrZ5Q==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "bmp-js": "^0.1.0",
+ "idb-keyval": "^6.2.0",
+ "is-electron": "^2.2.2",
+ "is-url": "^1.2.4",
+ "node-fetch": "^2.6.9",
+ "opencollective-postinstall": "^2.0.3",
+ "regenerator-runtime": "^0.13.3",
+ "tesseract.js-core": "^5.0.0",
+ "wasm-feature-detect": "^1.2.11",
+ "zlibjs": "^0.3.1"
+ }
+ },
+ "node_modules/tesseract.js-core": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmmirror.com/tesseract.js-core/-/tesseract.js-core-5.0.0.tgz",
+ "integrity": "sha512-lJur5LzjinW5VYMKlVNnBU2JPLpO+A9VqAYBeuV+ZgH0hKvsnm+536Yyp+/zRTBdLe7D6Kok0FN9g+TE4J8qGA=="
+ },
+ "node_modules/tesseract.js/node_modules/regenerator-runtime": {
+ "version": "0.13.11",
+ "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+ },
"node_modules/text-extensions": {
"version": "2.4.0",
"resolved": "https://registry.npmmirror.com/text-extensions/-/text-extensions-2.4.0.tgz",
@@ -8559,6 +8754,11 @@
"resolved": "https://registry.npmmirror.com/toggle-selection/-/toggle-selection-1.0.6.tgz",
"integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
},
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ },
"node_modules/trim-lines": {
"version": "3.0.1",
"resolved": "https://registry.npmmirror.com/trim-lines/-/trim-lines-3.0.1.tgz",
@@ -8605,6 +8805,14 @@
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
},
+ "node_modules/turndown": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmmirror.com/turndown/-/turndown-7.1.2.tgz",
+ "integrity": "sha512-ntI9R7fcUKjqBP6QU8rBK2Ehyt8LAzt3UBT9JR9tgo6GtuKvyUzpayWmeMKJw1DPdXzktvtIT8m2mVXz+bL/Qg==",
+ "dependencies": {
+ "domino": "^2.1.6"
+ }
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
@@ -8888,6 +9096,11 @@
"unist-util-stringify-position": "^3.0.0"
}
},
+ "node_modules/wasm-feature-detect": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmmirror.com/wasm-feature-detect/-/wasm-feature-detect-1.6.1.tgz",
+ "integrity": "sha512-R1i9ED8UlLu/foILNB1ck9XS63vdtqU/tP1MCugVekETp/ySCrBZRk5I/zI67cI1wlQYeSonNm1PLjDHZDNg6g=="
+ },
"node_modules/watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.0.tgz",
@@ -8900,6 +9113,20 @@
"node": ">=10.13.0"
}
},
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
@@ -9064,6 +9291,26 @@
"node": ">=0.8"
}
},
+ "node_modules/xml2js": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmmirror.com/xml2js/-/xml2js-0.6.2.tgz",
+ "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
+ "dependencies": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
"node_modules/xmorse": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/xmorse/-/xmorse-1.0.0.tgz",
@@ -9184,10 +9431,138 @@
"node": ">=10"
}
},
+ "node_modules/zlibjs": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmmirror.com/zlibjs/-/zlibjs-0.3.1.tgz",
+ "integrity": "sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/zwitch": {
"version": "2.0.4",
"resolved": "https://registry.npmmirror.com/zwitch/-/zwitch-2.0.4.tgz",
"integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz",
+ "integrity": "sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz",
+ "integrity": "sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz",
+ "integrity": "sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz",
+ "integrity": "sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz",
+ "integrity": "sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz",
+ "integrity": "sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-ia32-msvc": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz",
+ "integrity": "sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-x64-msvc": {
+ "version": "14.0.4",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz",
+ "integrity": "sha512-yEh2+R8qDlDCjxVpzOTEpBLQTEFAcP2A8fUFLaWNap9GitYKkKv1//y2S6XY6zsR4rCOPRpU7plYDR+az2n30A==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
}
}
}
diff --git a/package.json b/package.json
index a963e80..6632747 100644
--- a/package.json
+++ b/package.json
@@ -43,12 +43,16 @@
"change-case": "^5.3.0",
"compressorjs": "^1.2.1",
"crypto-js": "^4.2.0",
+ "css2less": "^0.1.4",
+ "dompurify": "^3.0.6",
"eslint-config-next": "^14.0.4",
"html-entities": "^2.4.0",
"ip": "^1.1.8",
"js-yaml": "^4.1.0",
"jsfuck": "^0.4.0",
"json-2-csv": "^5.0.1",
+ "less": "^4.2.0",
+ "marked": "^11.1.1",
"next": "^14.0.4",
"next-compose-plugins": "^2.2.1",
"next-transpile-modules": "^10.0.1",
@@ -76,8 +80,11 @@
"sql-formatter": "^15.0.2",
"sql.js": "^1.9.0",
"swiper": "^8.4.7",
+ "tesseract.js": "^5.0.4",
+ "turndown": "^7.1.2",
"typescript": "5.0.4",
"xlsx": "^0.18.5",
+ "xml2js": "^0.6.2",
"xmorse": "^1.0.0",
"yarn": "^1.22.21"
},
@@ -86,7 +93,9 @@
"@commitlint/config-conventional": "^18.4.3",
"@types/big-integer": "^0.0.31",
"@types/crypto-js": "^4.2.0",
+ "@types/dompurify": "^3.0.5",
"@types/ip": "^1.1.3",
+ "@types/less": "^3.0.6",
"@types/node": "20.1.5",
"@types/node-forge": "^1.3.10",
"@types/qs": "^6.9.7",
@@ -95,6 +104,8 @@
"@types/react-dom": "18.2.4",
"@types/react-syntax-highlighter": "^15.5.11",
"@types/sql.js": "^1.4.9",
+ "@types/turndown": "^5.0.4",
+ "@types/xml2js": "^0.4.14",
"@typescript-eslint/eslint-plugin": "^6.15.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
diff --git a/src/pages/json2xml.tsx b/src/pages/json2xml.tsx
new file mode 100644
index 0000000..59a21c9
--- /dev/null
+++ b/src/pages/json2xml.tsx
@@ -0,0 +1,293 @@
+import MainContent from '@/components/MainContent';
+import alert from '@/components/Alert';
+import { Box, Button, Stack } from '@mui/material';
+import { useCallback, useEffect, useState } from 'react';
+import AceEditor from 'react-ace';
+import SwapHorizontalCircleIcon from '@mui/icons-material/SwapHorizontalCircle';
+import { CopyToClipboard } from 'react-copy-to-clipboard';
+import { parseStringPromise, Builder } from 'xml2js';
+
+import 'ace-builds/src-noconflict/ext-language_tools';
+import 'ace-builds/src-noconflict/theme-monokai';
+import 'ace-builds/src-noconflict/mode-json';
+import 'ace-builds/src-noconflict/mode-xml';
+
+/**
+ * A => json
+ * B => xml
+ *
+ * 适用于两种语言的互转模版
+ * 1. 更改 import ace-builds/src-noconflict/mode-*
+ * 2. 更改所有 enum 枚举值
+ * 3. 在 a2b() 函数和 b2a() 函数中添加转换逻辑 return 转换结果
+ * */
+
+// 转换顺序
+enum ConvertType {
+ A2B = 1,
+ B2A = 2,
+}
+// 导出文件 MIME 类型;未知设为空
+enum ConvertFileType {
+ A2B = 'application/json',
+ B2A = 'application/xml',
+}
+// 导出文件名;未知 MIME 类型补充后缀
+enum ExportType {
+ A2B = 'jsontoxml',
+ B2A = 'xmltojson',
+}
+// 按钮文字
+enum ButtonText {
+ A2B = 'JSON',
+ B2A = 'XML',
+}
+// 导入限制类型
+enum InputAccept {
+ A2B = '.json',
+ B2A = '.xml',
+}
+// ace 编辑器 mode 类型
+enum AceMode {
+ A2B = 'json',
+ B2A = 'xml',
+}
+
+const _C = () => {
+ const [a, setA] = useState('');
+ const [b, setB] = useState('');
+ const [convert, setConvert] = useState(ConvertType.A2B);
+ const [error, setError] = useState('');
+
+ // 处理 a2b
+ const a2b = async (v: string) => {
+ try {
+ const builder = new Builder();
+ const xml = builder.buildObject(JSON.parse(v));
+ setB(xml);
+ } catch (e) {
+ setError(String(e));
+ }
+ };
+
+ // 处理 b2a
+ const b2a = async (v: string) => {
+ try {
+ const json = await parseStringPromise(v, { explicitArray: false });
+ setA(JSON.stringify(json, null, 2));
+ } catch (e) {
+ setError(String(e) || '未知错误');
+ }
+ };
+
+ const saveStringToFile = () => {
+ const blob =
+ convert === ConvertType.A2B
+ ? new Blob([b], { type: ConvertFileType.B2A })
+ : new Blob([a], { type: ConvertFileType.A2B });
+ const link = document.createElement('a');
+ link.href = window.URL.createObjectURL(blob);
+ link.download =
+ convert === ConvertType.A2B ? ExportType.A2B : ExportType.B2A;
+
+ document.body.appendChild(link);
+ link.click();
+
+ document.body.removeChild(link);
+ };
+
+ const handleClick = useCallback(() => {
+ alert.success('复制成功');
+ }, []);
+
+ const handleButtonClick = () => {
+ const fileInput = document.getElementById('fileInput');
+ fileInput?.click();
+ };
+
+ const handleFileChange = (event: any) => {
+ const file = event.target.files[0];
+ if (file) {
+ console.log(
+ '🐵 ~ file: json2xml.tsx:112 ~ handleFileChange ~ file:',
+ file
+ );
+ if (
+ file.type ===
+ (convert === ConvertType.A2B
+ ? ConvertFileType.A2B
+ : ConvertFileType.B2A)
+ ) {
+ const reader = new FileReader();
+ reader.onload = (e: any) => {
+ const content = e.target.result;
+ if (convert === ConvertType.A2B) {
+ setA(content);
+ } else setB(content);
+ setError('');
+ };
+
+ reader.readAsText(file);
+ } else {
+ setA('');
+ setError('Invalid file type.');
+ }
+ }
+ };
+
+ useEffect(() => {
+ if (a.trim() === '') {
+ setB('');
+ setError('');
+ return;
+ }
+ if (convert === ConvertType.A2B) {
+ try {
+ a2b(a);
+ setError('');
+ } catch (e) {
+ setError(String(e));
+ }
+ }
+ }, [a, convert]);
+
+ useEffect(() => {
+ if (!b) {
+ setA('');
+ setError('');
+ return;
+ }
+ if (convert === ConvertType.B2A) {
+ // 判断是否是数组或对象
+ try {
+ b2a(b);
+ setError('');
+ } catch (e) {
+ setError(String(e));
+ }
+ } else {
+ setError('');
+ }
+ }, [b, convert]);
+
+ return (
+
+
+
+
+
+
+ {convert === ConvertType.B2A ? ButtonText.B2A : ButtonText.A2B}
+
+
+
+ setConvert(
+ convert === ConvertType.B2A ? ConvertType.A2B : ConvertType.B2A
+ )
+ }
+ >
+
+
+
+
+ {convert === ConvertType.B2A ? ButtonText.A2B : ButtonText.B2A}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default _C;
diff --git a/src/pages/less2css.tsx b/src/pages/less2css.tsx
new file mode 100644
index 0000000..22f5f98
--- /dev/null
+++ b/src/pages/less2css.tsx
@@ -0,0 +1,289 @@
+import MainContent from '@/components/MainContent';
+import alert from '@/components/Alert';
+import { Box, Button, Stack } from '@mui/material';
+import { useCallback, useEffect, useState } from 'react';
+import AceEditor from 'react-ace';
+import SwapHorizontalCircleIcon from '@mui/icons-material/SwapHorizontalCircle';
+import { CopyToClipboard } from 'react-copy-to-clipboard';
+import LESS from 'less';
+import c2l from 'css2less';
+
+import 'ace-builds/src-noconflict/ext-language_tools';
+import 'ace-builds/src-noconflict/theme-monokai';
+import 'ace-builds/src-noconflict/mode-less';
+import 'ace-builds/src-noconflict/mode-css';
+
+/**
+ * A => Less
+ * B => CSS
+ *
+ * 适用于两种语言的互转模版
+ * 1. 更改 import ace-builds/src-noconflict/mode-*
+ * 2. 更改所有 enum 枚举值
+ * 3. 在 a2b() 函数和 b2a() 函数中添加转换逻辑 return 转换结果
+ * */
+
+// 转换顺序
+enum ConvertType {
+ A2B = 1,
+ B2A = 2,
+}
+// 导出文件 MIME 类型;未知设为空
+enum ConvertFileType {
+ A2B = 'text/css',
+ B2A = '',
+}
+// 导出文件名;未知 MIME 类型补充后缀
+enum ExportType {
+ A2B = 'lesstocss',
+ B2A = 'csstoless.less',
+}
+// 按钮文字
+enum ButtonText {
+ A2B = 'LESS',
+ B2A = 'CSS',
+}
+// 导入限制类型
+enum InputAccept {
+ A2B = '.less',
+ B2A = '.css',
+}
+// ace 编辑器 mode 类型
+enum AceMode {
+ A2B = 'less',
+ B2A = 'css',
+}
+
+const _C = () => {
+ const [a, setA] = useState('');
+ const [b, setB] = useState('');
+ const [convert, setConvert] = useState(ConvertType.A2B);
+ const [error, setError] = useState('');
+
+ // 处理 a2b
+ const a2b = async (v: string) => {
+ try {
+ const res = await LESS.render(v);
+ setB(res.css);
+ } catch (e) {
+ setError(String(e));
+ }
+ };
+
+ // 处理 b2a
+ const b2a = async (v: string) => {
+ try {
+ const res = await c2l(v, {});
+ setA(res);
+ } catch (e) {
+ setError(String(e) || '未知错误');
+ }
+ };
+
+ const saveStringToFile = () => {
+ const blob =
+ convert === ConvertType.A2B
+ ? new Blob([b], { type: ConvertFileType.A2B })
+ : new Blob([a], { type: ConvertFileType.B2A });
+ const link = document.createElement('a');
+ link.href = window.URL.createObjectURL(blob);
+ link.download =
+ convert === ConvertType.A2B ? ExportType.A2B : ExportType.B2A;
+
+ document.body.appendChild(link);
+ link.click();
+
+ document.body.removeChild(link);
+ };
+
+ const handleClick = useCallback(() => {
+ alert.success('复制成功');
+ }, []);
+
+ const handleButtonClick = () => {
+ const fileInput = document.getElementById('fileInput');
+ fileInput?.click();
+ };
+
+ const handleFileChange = (event: any) => {
+ const file = event.target.files[0];
+ if (file) {
+ if (
+ file.type ===
+ (convert === ConvertType.A2B
+ ? ConvertFileType.B2A
+ : ConvertFileType.A2B)
+ ) {
+ const reader = new FileReader();
+ reader.onload = (e: any) => {
+ const content = e.target.result;
+ if (convert === ConvertType.A2B) {
+ setA(content);
+ } else setB(content);
+ setError('');
+ };
+
+ reader.readAsText(file);
+ } else {
+ setA('');
+ setError('Invalid file type.');
+ }
+ }
+ };
+
+ useEffect(() => {
+ if (a.trim() === '') {
+ setB('');
+ setError('');
+ return;
+ }
+ if (convert === ConvertType.A2B) {
+ try {
+ a2b(a);
+ setError('');
+ } catch (e) {
+ setError(String(e));
+ }
+ }
+ }, [a, convert]);
+
+ useEffect(() => {
+ if (!b) {
+ setA('');
+ setError('');
+ return;
+ }
+ if (convert === ConvertType.B2A) {
+ // 判断是否是数组或对象
+ try {
+ b2a(b);
+ setError('');
+ } catch (e) {
+ setError(String(e));
+ }
+ } else {
+ setError('');
+ }
+ }, [b, convert]);
+
+ return (
+
+
+
+
+
+
+ {convert === ConvertType.B2A ? ButtonText.B2A : ButtonText.A2B}
+
+
+
+ setConvert(
+ convert === ConvertType.B2A ? ConvertType.A2B : ConvertType.B2A
+ )
+ }
+ >
+
+
+
+
+ {convert === ConvertType.B2A ? ButtonText.A2B : ButtonText.B2A}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default _C;
diff --git a/src/pages/md2html.tsx b/src/pages/md2html.tsx
new file mode 100644
index 0000000..31ef12e
--- /dev/null
+++ b/src/pages/md2html.tsx
@@ -0,0 +1,310 @@
+import MainContent from '@/components/MainContent';
+import alert from '@/components/Alert';
+import { Box, Button, Stack } from '@mui/material';
+import { useCallback, useEffect, useState } from 'react';
+import AceEditor from 'react-ace';
+import SwapHorizontalCircleIcon from '@mui/icons-material/SwapHorizontalCircle';
+import { CopyToClipboard } from 'react-copy-to-clipboard';
+import TurndownService from 'turndown';
+import { marked } from 'marked';
+import * as DOMPurify from 'dompurify';
+
+import 'ace-builds/src-noconflict/ext-language_tools';
+import 'ace-builds/src-noconflict/theme-monokai';
+import 'ace-builds/src-noconflict/mode-html';
+import 'ace-builds/src-noconflict/mode-markdown';
+
+/**
+ * A => markdown
+ * B => html
+ *
+ * 适用于两种语言的互转模版
+ * 1. 更改 import ace-builds/src-noconflict/mode-*
+ * 2. 更改所有 enum 枚举值
+ * 3. 在 a2b() 函数和 b2a() 函数中添加转换逻辑 return 转换结果
+ * */
+
+// 转换顺序
+enum ConvertType {
+ A2B = 1,
+ B2A = 2,
+}
+// 导出文件 MIME 类型;未知设为空
+enum ConvertFileType {
+ A2B = 'text/html',
+ B2A = '',
+}
+// 导出文件名;未知 MIME 类型补充后缀
+enum ExportType {
+ A2B = 'mdtohtml',
+ B2A = 'htmltomd.md',
+}
+// 按钮文字
+enum ButtonText {
+ A2B = 'MARKDOWN',
+ B2A = 'HTML',
+}
+// 导入限制类型
+enum InputAccept {
+ A2B = '.md',
+ B2A = '.html',
+}
+// ace 编辑器 mode 类型
+enum AceMode {
+ A2B = 'markdown',
+ B2A = 'html',
+}
+
+const _C = () => {
+ const [a, setA] = useState('');
+ const [b, setB] = useState('');
+ const [convert, setConvert] = useState(ConvertType.A2B);
+ const [error, setError] = useState('');
+
+ const postprocess = (v: string) => {
+ return DOMPurify.sanitize(v);
+ };
+
+ marked.use({
+ pedantic: false,
+ gfm: true,
+ breaks: false,
+ hooks: {
+ postprocess,
+ },
+ });
+
+ // 处理 a2b
+ const a2b = async (v: string) => {
+ try {
+ const html = await marked.parse(
+ v.replace(/^[\u200B\u200C\u200D\u200E\u200F\uFEFF]/, '')
+ );
+ setB(html);
+ } catch (e) {
+ setError(String(e));
+ }
+ };
+
+ // 处理 b2a
+ const b2a = async (v: string) => {
+ try {
+ const td = new TurndownService({
+ headingStyle: 'atx',
+ hr: '---',
+ codeBlockStyle: 'fenced',
+ });
+ const md = await td.turndown(v);
+ setA(md);
+ } catch (e) {
+ setError(String(e) || '未知错误');
+ }
+ };
+
+ const saveStringToFile = () => {
+ const blob =
+ convert === ConvertType.A2B
+ ? new Blob([b], { type: ConvertFileType.A2B })
+ : new Blob([a], { type: ConvertFileType.B2A });
+ const link = document.createElement('a');
+ link.href = window.URL.createObjectURL(blob);
+ link.download =
+ convert === ConvertType.A2B ? ExportType.A2B : ExportType.B2A;
+
+ document.body.appendChild(link);
+ link.click();
+
+ document.body.removeChild(link);
+ };
+
+ const handleClick = useCallback(() => {
+ alert.success('复制成功');
+ }, []);
+
+ const handleButtonClick = () => {
+ const fileInput = document.getElementById('fileInput');
+ fileInput?.click();
+ };
+
+ const handleFileChange = (event: any) => {
+ const file = event.target.files[0];
+ if (file) {
+ if (
+ file.type ===
+ (convert === ConvertType.A2B
+ ? ConvertFileType.B2A
+ : ConvertFileType.A2B)
+ ) {
+ const reader = new FileReader();
+ reader.onload = (e: any) => {
+ const content = e.target.result;
+ if (convert === ConvertType.A2B) {
+ setA(content);
+ } else setB(content);
+ setError('');
+ };
+
+ reader.readAsText(file);
+ } else {
+ setA('');
+ setError('Invalid file type.');
+ }
+ }
+ };
+
+ useEffect(() => {
+ if (a.trim() === '') {
+ setB('');
+ setError('');
+ return;
+ }
+ if (convert === ConvertType.A2B) {
+ try {
+ a2b(a);
+ setError('');
+ } catch (e) {
+ setError(String(e));
+ }
+ }
+ }, [a, convert]);
+
+ useEffect(() => {
+ if (!b) {
+ setA('');
+ setError('');
+ return;
+ }
+ if (convert === ConvertType.B2A) {
+ // 判断是否是数组或对象
+ try {
+ b2a(b);
+ setError('');
+ } catch (e) {
+ setError(String(e));
+ }
+ } else {
+ setError('');
+ }
+ }, [b, convert]);
+
+ return (
+
+
+
+
+
+
+ {convert === ConvertType.B2A ? ButtonText.B2A : ButtonText.A2B}
+
+
+
+ setConvert(
+ convert === ConvertType.B2A ? ConvertType.A2B : ConvertType.B2A
+ )
+ }
+ >
+
+
+
+
+ {convert === ConvertType.B2A ? ButtonText.A2B : ButtonText.B2A}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default _C;
diff --git a/src/pages/ocr.tsx b/src/pages/ocr.tsx
new file mode 100644
index 0000000..319ef7e
--- /dev/null
+++ b/src/pages/ocr.tsx
@@ -0,0 +1,112 @@
+import alertActions from '@/components/Alert';
+import MainContent from '@/components/MainContent';
+import { Box, Button } from '@mui/material';
+import { useCallback, useState } from 'react';
+import CopyToClipboard from 'react-copy-to-clipboard';
+import { createWorker } from 'tesseract.js';
+
+const sxWrap = {
+ fontSize: '12px',
+ p: 2,
+ mt: 2,
+ borderRadius: '4px',
+ backgroundColor: 'rgba(0, 0, 0, 0.05)',
+ color: 'rgba(0, 0, 0, 0.5)',
+};
+
+const _C = () => {
+ const [text, setText] = useState('');
+ const [error, setError] = useState('');
+ const [status, setStatus] = useState('');
+
+ const upload = () => {
+ const fileInput = document.getElementById('fileInput');
+ fileInput?.click();
+ };
+
+ const copy = useCallback(() => {
+ alertActions.success('复制成功');
+ }, []);
+
+ const convert = async (e: React.ChangeEvent) => {
+ const file = e.target.files?.[0];
+ if (file) {
+ setText('');
+ setError('');
+ try {
+ const imgUrl = URL.createObjectURL(file);
+
+ const worker = await createWorker(
+ 'eng+chi_sim+rus+deu+fra+jpn+kor',
+ 1,
+ {
+ logger: (m) => {
+ setStatus(
+ JSON.stringify({
+ status: m.status,
+ progress: (m.progress * 100).toFixed(2) + '%',
+ })
+ );
+ },
+ }
+ );
+ const res: any = await worker.recognize(imgUrl);
+ setText(res.data.text);
+ } catch (error) {
+ setError(String(error));
+ }
+ }
+ };
+
+ return (
+
+
+
+
+
+ {text
+ ? '识别成功'
+ : status || '点击上方按钮,上传图片即可识别图片中的文字!'}
+
+ {text && (
+
+
+ {text}
+
+
+
+ 复制
+
+
+
+ )}
+ {error && {error}}
+
+
+ );
+};
+
+export default _C;
diff --git a/src/utils/tools.ts b/src/utils/tools.ts
index 0a054ee..748218c 100644
--- a/src/utils/tools.ts
+++ b/src/utils/tools.ts
@@ -381,4 +381,32 @@ export const allTools: Tool[] = [
key: [],
subTitle: '在线颜色吸取器,可以快速生成十种常用颜色的代码',
},
+ {
+ label: 'LESS CSS 互转',
+ tags: [Tags.DEV],
+ path: '/less2css',
+ key: [],
+ subTitle: '支持 less 转 css,css 转 less',
+ },
+ {
+ label: 'markdown html 格式互转',
+ tags: [Tags.DEV],
+ path: '/md2html',
+ key: [],
+ subTitle: 'markdown html 格式互转',
+ },
+ {
+ label: 'JSON XML 互转',
+ tags: [Tags.JSON],
+ path: '/json2xml',
+ key: [],
+ subTitle: 'JSON 转 XML,XML 转 JSON',
+ },
+ {
+ label: '图片 OCR 识别',
+ tags: [Tags.IMAGE],
+ path: '/ocr',
+ key: [],
+ subTitle: '支持识别中文、英语、俄语、德语、法语、日语、韩语',
+ },
];
diff --git a/tsconfig.json b/tsconfig.json
index 6b546c9..4e8ca24 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -18,6 +18,6 @@
"@/*": ["./src/*"]
}
},
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "imgLoader.js"],
+ "include": ["next-env.d.ts", "*.d.ts", "**/*.ts", "**/*.tsx", "imgLoader.js"],
"exclude": ["node_modules"]
}