diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7dc3877..43e4116 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,8 +29,8 @@ jobs: # ghcr.io/cross-rs/aarch64-unknown-linux-gnu:main runs-on: ${{ matrix.platform }} - # container: - # image: ${{ matrix.image }} + container: + image: ${{ matrix.image }} steps: diff --git a/README.md b/README.md index 96491df..13b395b 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ ## 主要功能 本地离线工具集合,包含以下功能: - base64转码/解码:文本转base64,base64转文本,图片转base64,base64转图片 +- 正则表达式 - 格式化:格式化json/yaml/xml - urlEncode/urlDecode - 摘要算法:计算文本的md5,sha256。计算多个文件的md5,sha256 @@ -10,6 +11,8 @@ - 调色板 - 文本对比工具 - 国密算法(SM2,SM3,SM4) +- 国际化:支持中文,英文 +- 支持菜单项重排:将自己常用的功能置顶。 ## relase 下载地址 https://github.com/lsk569937453/code-magic-public/releases diff --git a/package.json b/package.json index 371ab08..5d84126 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "cmdk": "^0.2.0", "date-fns": "^2.30.0", "i18next": "^23.7.11", + "i18next-browser-languagedetector": "^7.2.0", "lucide-react": "^0.263.1", "next-themes": "^0.2.1", "react": "^18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b07790d..0ae997d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -113,6 +113,9 @@ dependencies: i18next: specifier: ^23.7.11 version: 23.7.11 + i18next-browser-languagedetector: + specifier: ^7.2.0 + version: 7.2.0 lucide-react: specifier: ^0.263.1 version: 0.263.1(react@18.2.0) @@ -3177,7 +3180,7 @@ packages: /dom-helpers@3.4.0: resolution: {integrity: sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==} dependencies: - '@babel/runtime': 7.21.5 + '@babel/runtime': 7.23.6 dev: false /eastasianwidth@0.2.0: @@ -3482,6 +3485,12 @@ packages: ms: 2.1.2 dev: true + /i18next-browser-languagedetector@7.2.0: + resolution: {integrity: sha512-U00DbDtFIYD3wkWsr2aVGfXGAj2TgnELzOX9qv8bT0aJtvPV9CRO77h+vgmHFBMe7LAxdwvT/7VkCWGya6L3tA==} + dependencies: + '@babel/runtime': 7.23.6 + dev: false + /i18next@23.7.11: resolution: {integrity: sha512-A/vOkw8vY99YHU9A1Td3I1dcTiYaPnwBWzrpVzfXUXSYgogK3cmBcmop/0cnXPc6QpUWIyqaugKNxRUEZVk9Nw==} dependencies: diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index b9b8265..ed26403 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -403,7 +403,7 @@ dependencies = [ [[package]] name = "code_magic" -version = "0.0.19" +version = "0.0.20" dependencies = [ "aes", "anyhow", @@ -427,6 +427,7 @@ dependencies = [ "serde_repr", "serde_yaml", "sha2", + "sqlformat", "tauri", "tauri-build", "tauri-plugin-log", @@ -1629,6 +1630,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" @@ -1969,6 +1979,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -2030,6 +2046,16 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3180,6 +3206,17 @@ dependencies = [ "lock_api", ] +[[package]] +name = "sqlformat" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -3903,6 +3940,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "unsafe-libyaml" version = "0.2.9" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d1e3645..1ed864d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "code_magic" -version = "0.0.19" +version = "0.0.20" description = "A development tools" authors = ["lsk"] license = "MIT" @@ -45,6 +45,7 @@ hex = "0.4" num = "0.4" rusqlite = { version = "0.30.0", features = ["bundled"] } serde_repr = "0.1.17" +sqlformat = "0.2.3" [features] # by default Tauri runs in production mode # when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL diff --git a/src-tauri/src/common_tools/cmd.rs b/src-tauri/src/common_tools/cmd.rs index 1783516..fb885fc 100644 --- a/src-tauri/src/common_tools/cmd.rs +++ b/src-tauri/src/common_tools/cmd.rs @@ -14,6 +14,7 @@ use crate::common_tools::crypto_algorithm::sm4_decrypt_with_error; use crate::common_tools::crypto_algorithm::sm4_encrypt_with_error; use crate::common_tools::crypto_algorithm::Sm2EncryptRequest; use crate::common_tools::crypto_algorithm::Sm4EncryptRequest; +use crate::common_tools::format::foramt_pretty_sql_with_error; use crate::common_tools::format::format_pretty_json_with_error; use crate::common_tools::format::format_pretty_yaml_with_error; use crate::common_tools::format::format_xml_with_error; @@ -517,6 +518,25 @@ pub fn format_pretty_xml(source_string: String) -> String { } } #[tauri::command] +pub fn foramt_pretty_sql(source_string: String) -> String { + match foramt_pretty_sql_with_error(source_string) { + Ok(item) => { + let res = BaseResponse { + response_code: 0, + response_msg: item, + }; + serde_json::to_string(&res).unwrap() + } + Err(e) => { + let res = BaseResponse { + response_code: 1, + response_msg: e.to_string(), + }; + serde_json::to_string(&res).unwrap() + } + } +} +#[tauri::command] pub fn get_about_version() -> String { match get_about_version_with_error() { Ok(item) => { diff --git a/src-tauri/src/common_tools/format.rs b/src-tauri/src/common_tools/format.rs index 5d441d5..0241f84 100644 --- a/src-tauri/src/common_tools/format.rs +++ b/src-tauri/src/common_tools/format.rs @@ -1,6 +1,6 @@ use quick_xml::events::Event; use quick_xml::{Reader, Writer}; - +use sqlformat::*; pub fn format_pretty_json_with_error(source_string: String) -> Result { let source: serde_json::value::Value = serde_json::from_str(&source_string).map_err(|e| anyhow::anyhow!(e))?; @@ -14,6 +14,14 @@ pub fn format_pretty_yaml_with_error(source_string: String) -> Result Result { + let res = format( + source_string.as_str(), + &QueryParams::None, + FormatOptions::default(), + ); + Ok(res) +} pub fn format_xml_with_error(source_string: String) -> Result { let mut buf = Vec::new(); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 70aa54c..74681ab 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -110,6 +110,7 @@ fn main() -> Result<(), anyhow::Error> { format_pretty_json, format_pretty_yaml, format_pretty_xml, + foramt_pretty_sql, get_about_version, get_menu_config, set_menu_index, diff --git a/src/dashboard/page/base64TextPage.tsx b/src/dashboard/page/base64TextPage.tsx index 0197157..96499b2 100644 --- a/src/dashboard/page/base64TextPage.tsx +++ b/src/dashboard/page/base64TextPage.tsx @@ -14,7 +14,6 @@ export function Base64TextPage() { const { toast } = useToast() const base64Encode = async () => { - i18n.changeLanguage("zh"); if (currentInput === undefined || currentInput === "") { toast({ variant: "destructive", @@ -32,7 +31,6 @@ export function Base64TextPage() { } } const base64Decode = async () => { - i18n.changeLanguage("en"); if (currentInput === undefined || currentInput === "") { toast({ diff --git a/src/dashboard/page/diffViewerPage.tsx b/src/dashboard/page/diffViewerPage.tsx index f1555b3..00011d3 100644 --- a/src/dashboard/page/diffViewerPage.tsx +++ b/src/dashboard/page/diffViewerPage.tsx @@ -121,8 +121,14 @@ export default function DiffViewerPage() { setDifferValue(finalResult); } const differValueOnChange = (v: any) => { - console.log(v); - setDifferValue(v); + const [arr1,arr2]=v; + const newArr1=arr1.replaceAll('\r\n', '\n'); + const newArr2=arr2.replaceAll('\r\n', '\n'); + const newV=[]; + newV.push(newArr1); + newV.push(newArr2); + + setDifferValue(newV); } return (
diff --git a/src/dashboard/page/formatPage.tsx b/src/dashboard/page/formatPage.tsx index e486aad..11ef3b8 100644 --- a/src/dashboard/page/formatPage.tsx +++ b/src/dashboard/page/formatPage.tsx @@ -4,20 +4,21 @@ import FormatJsonPage from "./formatJsonPage"; import FormatYamlPage from './formatYamlPage'; import FormatXmlPage from "./formatXmlPage" - +import FormatSqlPage from "./formatSqlPage"; export default function FormatPage() { return ( - + JSON YAML XML + SQL - + ); } \ No newline at end of file diff --git a/src/dashboard/page/formatSqlPage.tsx b/src/dashboard/page/formatSqlPage.tsx new file mode 100644 index 0000000..8a5ff3c --- /dev/null +++ b/src/dashboard/page/formatSqlPage.tsx @@ -0,0 +1,91 @@ +import { Textarea } from "@/components/ui/textarea" +import { useState } from "react" +import { invoke } from "@tauri-apps/api/tauri"; +import { Button } from "@/components/ui/button" +import { Card } from "@/components/ui/card" +import AceEditor from "react-ace"; +import { useTheme } from "next-themes" +import { useToast } from "@/components/ui/use-toast" + +import "ace-builds/src-noconflict/snippets/xml"; +import "ace-builds/src-noconflict/mode-sql"; +import "ace-builds/src-noconflict/theme-github"; + +import "ace-builds/src-noconflict/theme-monokai"; + +import "ace-builds/src-noconflict/ext-language_tools"; +import { useTranslation, Trans } from "react-i18next"; + +export default function FormatSqlPage() { + const [currentInput, setCurrentInput] = useState(); + const [validJson, setValidJson] = useState(null); + const { setTheme, theme } = useTheme() + const { toast } = useToast() + const { t, i18n } = useTranslation(); + + const formatPrettyJson = async () => { + if (currentInput === undefined || currentInput === "") { + toast({ + variant: "destructive", + title: t('toastMessage.errorMessageTile'), + description: t('jsonFormatPage.sourceNotEmptyMessageBody'), + }) + return; + } + const { response_code, response_msg } = JSON.parse(await invoke("foramt_pretty_sql", { sourceString: currentInput })); + console.log(response_code); + + if (response_code === 0) { + setCurrentInput(response_msg); + let json = JSON.parse(response_msg); + setValidJson(json); + + } else { + toast({ + variant: "destructive", + title: t('toastMessage.errorMessageTile'), + description: t('jsonFormatPage.sourceNotValidMessageBody'), + }) + } + } + + const handleValueChange = (e: any) => { + setCurrentInput(e); + } + + return ( +
+
+ +
+
+ +
+ +
+ ); +} \ No newline at end of file diff --git a/src/dashboard/page/regexPage.tsx b/src/dashboard/page/regexPage.tsx index 0ce2313..6c563a8 100644 --- a/src/dashboard/page/regexPage.tsx +++ b/src/dashboard/page/regexPage.tsx @@ -1,5 +1,5 @@ import { Input } from "@/components/ui/input" -import { useState, useRef } from "react" +import { useState, useRef, useEffect } from "react" import { invoke } from "@tauri-apps/api/tauri"; import { Button } from "@/components/ui/button" import { useToast } from "@/components/ui/use-toast" @@ -19,21 +19,19 @@ import { useTheme } from "next-themes" export function RegexPage() { const { t, i18n } = useTranslation(); - const [currentRegex, setCurrentRegex] = useState(); - const [currentInput, setCurrentInput] = useState(); + const [currentRegex, setCurrentRegex] = useState('([A-Z])\\w+'); + const [currentInput, setCurrentInput] = useState("RegExr was created by gskinner.com. Edit the Expression & Text to see matches. Roll over matches or the expression for details. PCRE & JavaScript flavors of RegEx are supported. Validate your expression with Tests mode. The side bar includes a Cheatsheet, full Reference, and Help. You can also Save & Share with the Community and view patterns you create or favorite in My Patterns. Explore results with the Tools below. Replace & List output custom results. Details lists capture groups. Explain describes your expression in plain English."); const { toast } = useToast() const { setTheme, theme } = useTheme() const aceEditorRef = useRef(null); + useEffect(() => { + showRegex(currentRegex); + }, []) - const handleRegexInputOnChange = (t: any) => { - // const e = require("ace-builds/src-noconflict/ext-searchbox"); - // e.Search(aceEditorRef.current?.editor, true); - setCurrentRegex(t.target.value); - console.log("t is:",t); - // const regex = new RegExp('([A-Z])\\w+', 'gm'); - // const regex2 = /([A-Z])\w+/gm; - const regex = new RegExp(t.target.value, 'gm'); + const showRegex=(v:any)=>{ + console.log("v is :"+v); + const regex = new RegExp(v, 'gm'); // regexpX.test(:'RegExr was created by gskinner.com'); console.log(aceEditorRef.current); // aceEditorRef.current?.editor.findAll(regexp,{ @@ -61,6 +59,12 @@ export function RegexPage() { aceEditorRef.current?.editor.getSession().addMarker(element, "searchMarker", "text"); }); + } + const handleRegexInputOnChange = (t: any) => { + // const e = require("ace-builds/src-noconflict/ext-searchbox"); + // e.Search(aceEditorRef.current?.editor, true); + setCurrentRegex(t.target.value); + showRegex(t.target.value); } @@ -72,7 +76,7 @@ export function RegexPage() { <>
- +
diff --git a/src/i18n.ts b/src/i18n.ts index d0513d3..d016a20 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -2,10 +2,16 @@ import i18next from 'i18next'; import enMain from './locales/en/main.json'; import zhMain from './locales/zh/main.json'; import { initReactI18next } from 'react-i18next'; +import LanguageDetector from 'i18next-browser-languagedetector'; + export const defaultNS = 'main'; +const DETECTION_OPTIONS = { + order: ['localStorage', 'navigator'], + caches: ['localStorage'] +}; -i18next.use(initReactI18next).init({ +i18next.use(LanguageDetector).use(initReactI18next).init({ debug: true, fallbackLng: 'en', defaultNS, @@ -18,6 +24,8 @@ i18next.use(initReactI18next).init({ }, }, initImmediate: false, + detection: DETECTION_OPTIONS, + });