From 1951ed01e790105af34eeb346f394cff931bcdd5 Mon Sep 17 00:00:00 2001 From: imoyy Date: Fri, 5 Sep 2025 01:10:04 +0800 Subject: [PATCH 1/4] feat: add programming language icons to codeblock header. --- src/renderer/src/assets/images/lang/c.svg | 1 + src/renderer/src/assets/images/lang/cmake.svg | 1 + .../src/assets/images/lang/cplusplus.svg | 6 ++ .../src/assets/images/lang/csharp.svg | 1 + src/renderer/src/assets/images/lang/css3.svg | 1 + src/renderer/src/assets/images/lang/go.svg | 1 + src/renderer/src/assets/images/lang/java.svg | 1 + .../src/assets/images/lang/javascript.svg | 1 + src/renderer/src/assets/images/lang/json.svg | 1 + src/renderer/src/assets/images/lang/lua.svg | 1 + src/renderer/src/assets/images/lang/php.svg | 2 + .../src/assets/images/lang/python.svg | 1 + src/renderer/src/assets/images/lang/ruby.svg | 1 + src/renderer/src/assets/images/lang/rust.svg | 1 + .../src/assets/images/lang/typescript.svg | 1 + src/renderer/src/assets/images/lang/vb.svg | 1 + src/renderer/src/assets/images/lang/xml.svg | 1 + src/renderer/src/assets/images/lang/yaml.svg | 6 ++ .../src/components/CodeBlockView/view.tsx | 16 +++- src/renderer/src/config/lang.ts | 84 +++++++++++++++++++ 20 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 src/renderer/src/assets/images/lang/c.svg create mode 100644 src/renderer/src/assets/images/lang/cmake.svg create mode 100644 src/renderer/src/assets/images/lang/cplusplus.svg create mode 100644 src/renderer/src/assets/images/lang/csharp.svg create mode 100644 src/renderer/src/assets/images/lang/css3.svg create mode 100644 src/renderer/src/assets/images/lang/go.svg create mode 100644 src/renderer/src/assets/images/lang/java.svg create mode 100644 src/renderer/src/assets/images/lang/javascript.svg create mode 100644 src/renderer/src/assets/images/lang/json.svg create mode 100644 src/renderer/src/assets/images/lang/lua.svg create mode 100644 src/renderer/src/assets/images/lang/php.svg create mode 100644 src/renderer/src/assets/images/lang/python.svg create mode 100644 src/renderer/src/assets/images/lang/ruby.svg create mode 100644 src/renderer/src/assets/images/lang/rust.svg create mode 100644 src/renderer/src/assets/images/lang/typescript.svg create mode 100644 src/renderer/src/assets/images/lang/vb.svg create mode 100644 src/renderer/src/assets/images/lang/xml.svg create mode 100644 src/renderer/src/assets/images/lang/yaml.svg create mode 100644 src/renderer/src/config/lang.ts diff --git a/src/renderer/src/assets/images/lang/c.svg b/src/renderer/src/assets/images/lang/c.svg new file mode 100644 index 000000000..5197f2a95 --- /dev/null +++ b/src/renderer/src/assets/images/lang/c.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/src/assets/images/lang/cmake.svg b/src/renderer/src/assets/images/lang/cmake.svg new file mode 100644 index 000000000..0c1ab97bf --- /dev/null +++ b/src/renderer/src/assets/images/lang/cmake.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/src/assets/images/lang/cplusplus.svg b/src/renderer/src/assets/images/lang/cplusplus.svg new file mode 100644 index 000000000..6cae2226d --- /dev/null +++ b/src/renderer/src/assets/images/lang/cplusplus.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/renderer/src/assets/images/lang/csharp.svg b/src/renderer/src/assets/images/lang/csharp.svg new file mode 100644 index 000000000..acc487eb5 --- /dev/null +++ b/src/renderer/src/assets/images/lang/csharp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/src/assets/images/lang/css3.svg b/src/renderer/src/assets/images/lang/css3.svg new file mode 100644 index 000000000..ff5b6ce62 --- /dev/null +++ b/src/renderer/src/assets/images/lang/css3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/src/assets/images/lang/go.svg b/src/renderer/src/assets/images/lang/go.svg new file mode 100644 index 000000000..433778040 --- /dev/null +++ b/src/renderer/src/assets/images/lang/go.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/src/assets/images/lang/java.svg b/src/renderer/src/assets/images/lang/java.svg new file mode 100644 index 000000000..051bf254a --- /dev/null +++ b/src/renderer/src/assets/images/lang/java.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/src/assets/images/lang/javascript.svg b/src/renderer/src/assets/images/lang/javascript.svg new file mode 100644 index 000000000..7975261bd --- /dev/null +++ b/src/renderer/src/assets/images/lang/javascript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/src/assets/images/lang/json.svg b/src/renderer/src/assets/images/lang/json.svg new file mode 100644 index 000000000..90bb4d37b --- /dev/null +++ b/src/renderer/src/assets/images/lang/json.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/src/assets/images/lang/lua.svg b/src/renderer/src/assets/images/lang/lua.svg new file mode 100644 index 000000000..6b7ea4b08 --- /dev/null +++ b/src/renderer/src/assets/images/lang/lua.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/src/assets/images/lang/php.svg b/src/renderer/src/assets/images/lang/php.svg new file mode 100644 index 000000000..32b7a5b44 --- /dev/null +++ b/src/renderer/src/assets/images/lang/php.svg @@ -0,0 +1,2 @@ + + diff --git a/src/renderer/src/assets/images/lang/python.svg b/src/renderer/src/assets/images/lang/python.svg new file mode 100644 index 000000000..e0e096a24 --- /dev/null +++ b/src/renderer/src/assets/images/lang/python.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/src/assets/images/lang/ruby.svg b/src/renderer/src/assets/images/lang/ruby.svg new file mode 100644 index 000000000..9c651106b --- /dev/null +++ b/src/renderer/src/assets/images/lang/ruby.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/src/assets/images/lang/rust.svg b/src/renderer/src/assets/images/lang/rust.svg new file mode 100644 index 000000000..3f2c9b0ac --- /dev/null +++ b/src/renderer/src/assets/images/lang/rust.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/src/assets/images/lang/typescript.svg b/src/renderer/src/assets/images/lang/typescript.svg new file mode 100644 index 000000000..e1db5f196 --- /dev/null +++ b/src/renderer/src/assets/images/lang/typescript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/src/assets/images/lang/vb.svg b/src/renderer/src/assets/images/lang/vb.svg new file mode 100644 index 000000000..f10686a58 --- /dev/null +++ b/src/renderer/src/assets/images/lang/vb.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/src/assets/images/lang/xml.svg b/src/renderer/src/assets/images/lang/xml.svg new file mode 100644 index 000000000..bb16105b4 --- /dev/null +++ b/src/renderer/src/assets/images/lang/xml.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/src/assets/images/lang/yaml.svg b/src/renderer/src/assets/images/lang/yaml.svg new file mode 100644 index 000000000..56618856d --- /dev/null +++ b/src/renderer/src/assets/images/lang/yaml.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/renderer/src/components/CodeBlockView/view.tsx b/src/renderer/src/components/CodeBlockView/view.tsx index 46f6cbce8..37d543efb 100644 --- a/src/renderer/src/components/CodeBlockView/view.tsx +++ b/src/renderer/src/components/CodeBlockView/view.tsx @@ -16,6 +16,7 @@ import CodeViewer from '@renderer/components/CodeViewer' import ImageViewer from '@renderer/components/ImageViewer' import { BasicPreviewHandles } from '@renderer/components/Preview' import { MAX_COLLAPSED_CODE_HEIGHT } from '@renderer/config/constant' +import { getLangLogo } from '@renderer/config/lang' import { useSettings } from '@renderer/hooks/useSettings' import { pyodideService } from '@renderer/services/PyodideService' import { getExtensionByLanguage } from '@renderer/utils/code-language' @@ -282,8 +283,13 @@ export const CodeBlockView: React.FC = memo(({ children, language, onSave }, [children, codeImageTools, language]) const renderHeader = useMemo(() => { - const langTag = '<' + language.toUpperCase() + '>' - return {isInSpecialView ? '' : langTag} + const logo = getLangLogo(language) + return ( + + {logo ? {language} : ''} + {language} + + ) }, [isInSpecialView, language]) // 根据视图模式和语言选择组件,优先展示特殊视图,fallback是源代码视图 @@ -359,6 +365,12 @@ const CodeHeader = styled.div<{ $isInSpecialView?: boolean }>` margin-top: ${(props) => (props.$isInSpecialView ? '6px' : '0')}; height: ${(props) => (props.$isInSpecialView ? '16px' : '34px')}; background-color: ${(props) => (props.$isInSpecialView ? 'transparent' : 'var(--color-background-mute)')}; + + img { + width: 16px; + height: 16px; + margin-right: 8px; + } ` const SplitViewWrapper = styled.div<{ $isSpecialView: boolean; $isSplitView: boolean }>` diff --git a/src/renderer/src/config/lang.ts b/src/renderer/src/config/lang.ts new file mode 100644 index 000000000..975e9f59c --- /dev/null +++ b/src/renderer/src/config/lang.ts @@ -0,0 +1,84 @@ +/** + * @license + * The MIT License (MIT) + * + * Copyright (c) 2015 konpa + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +import CIcon from '@renderer/assets/images/lang/c.svg' +import CMakeIcon from '@renderer/assets/images/lang/cmake.svg' +import CppIcon from '@renderer/assets/images/lang/cplusplus.svg' +import CSharpIcon from '@renderer/assets/images/lang/csharp.svg' +import CSS3Icon from '@renderer/assets/images/lang/css3.svg' +import GoIcon from '@renderer/assets/images/lang/go.svg' +import JavaIcon from '@renderer/assets/images/lang/java.svg' +import JavaScriptIcon from '@renderer/assets/images/lang/javascript.svg' +import JsonIcon from '@renderer/assets/images/lang/json.svg' +import LuaIcon from '@renderer/assets/images/lang/lua.svg' +import PhpIcon from '@renderer/assets/images/lang/php.svg' +import PythonIcon from '@renderer/assets/images/lang/python.svg' +import RubyIcon from '@renderer/assets/images/lang/ruby.svg' +import RustIcon from '@renderer/assets/images/lang/rust.svg' +import TypeScriptIcon from '@renderer/assets/images/lang/typescript.svg' +import VBIcon from '@renderer/assets/images/lang/vb.svg' +import XMLIcon from '@renderer/assets/images/lang/xml.svg' +import YamlIcon from '@renderer/assets/images/lang/yaml.svg' +export function getLangLogo(lang: string) { + const isLight = true + + if (!lang) { + return undefined + } + + const logoMap = { + TS: isLight ? TypeScriptIcon : TypeScriptIcon, + TypeScript: isLight ? TypeScriptIcon : TypeScriptIcon, + JS: isLight ? JavaScriptIcon : JavaScriptIcon, + JavaScript: isLight ? JavaScriptIcon : JavaScriptIcon, + Python: isLight ? PythonIcon : PythonIcon, + PY: isLight ? PythonIcon : PythonIcon, + Java: isLight ? JavaIcon : JavaIcon, + CPP: isLight ? CppIcon : CppIcon, + CMake: isLight ? CMakeIcon : CMakeIcon, + '^c$': isLight ? CIcon : CIcon, + csharp: isLight ? CSharpIcon : CSharpIcon, + Go: isLight ? GoIcon : GoIcon, + Json: isLight ? JsonIcon : JsonIcon, + Rust: isLight ? RustIcon : RustIcon, + Yaml: isLight ? YamlIcon : YamlIcon, + Php: isLight ? PhpIcon : PhpIcon, + Ruby: isLight ? RubyIcon : RubyIcon, + Lua: isLight ? LuaIcon : LuaIcon, + CSS: isLight ? CSS3Icon : CSS3Icon, + CSS3: isLight ? CSS3Icon : CSS3Icon, + XML: isLight ? XMLIcon : XMLIcon, + vb: isLight ? VBIcon : VBIcon, + visualbasic: isLight ? VBIcon : VBIcon, + HTML: isLight ? XMLIcon : XMLIcon + } + + for (const key in logoMap) { + const regex = new RegExp(key, 'i') + if (regex.test(lang)) { + return logoMap[key] + } + } + + return undefined +} From de674ad5508074b37eb76a5c046df4f89a069422 Mon Sep 17 00:00:00 2001 From: imoyy Date: Fri, 5 Sep 2025 14:03:19 +0800 Subject: [PATCH 2/4] fix(types): correct type definition for SvgPreview.tsx. --- .../src/components/Preview/SvgPreview.tsx | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/renderer/src/components/Preview/SvgPreview.tsx b/src/renderer/src/components/Preview/SvgPreview.tsx index 673d7ded0..81dd279bb 100644 --- a/src/renderer/src/components/Preview/SvgPreview.tsx +++ b/src/renderer/src/components/Preview/SvgPreview.tsx @@ -3,20 +3,18 @@ import { memo, useCallback } from 'react' import { useDebouncedRender } from './hooks/useDebouncedRender' import ImagePreviewLayout from './ImagePreviewLayout' import { ShadowTransparentContainer } from './styles' -import { BasicPreviewHandles } from './types' +import { BasicPreviewHandles, type BasicPreviewProps } from './types' import { renderSvgInShadowHost } from './utils' -interface SvgPreviewProps { - children: string - enableToolbar?: boolean - className?: string - ref?: React.RefObject -} - /** * 使用 Shadow DOM 渲染 SVG */ -const SvgPreview = ({ children, enableToolbar = false, className, ref }: SvgPreviewProps) => { +const SvgPreview = ({ + children, + enableToolbar = false, + className, + ref +}: BasicPreviewProps & { ref?: React.RefObject } & { className?: string }) => { // 定义渲染函数 const renderSvg = useCallback(async (content: string, container: HTMLDivElement) => { renderSvgInShadowHost(content, container) From 6bab1a5ad86a04ac954244158b20a3789c4e0681 Mon Sep 17 00:00:00 2001 From: imoyy Date: Sat, 6 Sep 2025 13:39:04 +0800 Subject: [PATCH 3/4] fix: hide elements when `isInSpecialView` is true --- src/renderer/src/assets/images/lang/bash.svg | 1 + src/renderer/src/assets/images/lang/c.svg | 2 +- src/renderer/src/assets/images/lang/perl.svg | 1 + .../src/components/CodeBlockView/view.tsx | 18 ++++-- src/renderer/src/config/lang.ts | 56 ++++++++++--------- 5 files changed, 45 insertions(+), 33 deletions(-) create mode 100644 src/renderer/src/assets/images/lang/bash.svg create mode 100644 src/renderer/src/assets/images/lang/perl.svg diff --git a/src/renderer/src/assets/images/lang/bash.svg b/src/renderer/src/assets/images/lang/bash.svg new file mode 100644 index 000000000..8aade9d71 --- /dev/null +++ b/src/renderer/src/assets/images/lang/bash.svg @@ -0,0 +1 @@ + diff --git a/src/renderer/src/assets/images/lang/c.svg b/src/renderer/src/assets/images/lang/c.svg index 5197f2a95..740ffd822 100644 --- a/src/renderer/src/assets/images/lang/c.svg +++ b/src/renderer/src/assets/images/lang/c.svg @@ -1 +1 @@ - + diff --git a/src/renderer/src/assets/images/lang/perl.svg b/src/renderer/src/assets/images/lang/perl.svg new file mode 100644 index 000000000..49f367388 --- /dev/null +++ b/src/renderer/src/assets/images/lang/perl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/renderer/src/components/CodeBlockView/view.tsx b/src/renderer/src/components/CodeBlockView/view.tsx index 37d543efb..799021295 100644 --- a/src/renderer/src/components/CodeBlockView/view.tsx +++ b/src/renderer/src/components/CodeBlockView/view.tsx @@ -286,8 +286,14 @@ export const CodeBlockView: React.FC = memo(({ children, language, onSave const logo = getLangLogo(language) return ( - {logo ? {language} : ''} - {language} + {isInSpecialView ? ( + '' + ) : ( + <> + {logo && {language}} + {language} + + )} ) }, [isInSpecialView, language]) @@ -356,7 +362,7 @@ const CodeHeader = styled.div<{ $isInSpecialView?: boolean }>` display: flex; align-items: center; color: var(--color-text); - font-size: 14px; + font-size: 13px; line-height: 1; font-weight: bold; padding: 0 10px; @@ -367,9 +373,9 @@ const CodeHeader = styled.div<{ $isInSpecialView?: boolean }>` background-color: ${(props) => (props.$isInSpecialView ? 'transparent' : 'var(--color-background-mute)')}; img { - width: 16px; - height: 16px; - margin-right: 8px; + width: 12px; + height: 12px; + margin-right: 6px; } ` diff --git a/src/renderer/src/config/lang.ts b/src/renderer/src/config/lang.ts index 975e9f59c..dbcfe5fec 100644 --- a/src/renderer/src/config/lang.ts +++ b/src/renderer/src/config/lang.ts @@ -21,6 +21,7 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +import BashIcon from '@renderer/assets/images/lang/bash.svg' import CIcon from '@renderer/assets/images/lang/c.svg' import CMakeIcon from '@renderer/assets/images/lang/cmake.svg' import CppIcon from '@renderer/assets/images/lang/cplusplus.svg' @@ -31,6 +32,7 @@ import JavaIcon from '@renderer/assets/images/lang/java.svg' import JavaScriptIcon from '@renderer/assets/images/lang/javascript.svg' import JsonIcon from '@renderer/assets/images/lang/json.svg' import LuaIcon from '@renderer/assets/images/lang/lua.svg' +import PerlIcon from '@renderer/assets/images/lang/perl.svg' import PhpIcon from '@renderer/assets/images/lang/php.svg' import PythonIcon from '@renderer/assets/images/lang/python.svg' import RubyIcon from '@renderer/assets/images/lang/ruby.svg' @@ -40,37 +42,39 @@ import VBIcon from '@renderer/assets/images/lang/vb.svg' import XMLIcon from '@renderer/assets/images/lang/xml.svg' import YamlIcon from '@renderer/assets/images/lang/yaml.svg' export function getLangLogo(lang: string) { - const isLight = true - if (!lang) { return undefined } const logoMap = { - TS: isLight ? TypeScriptIcon : TypeScriptIcon, - TypeScript: isLight ? TypeScriptIcon : TypeScriptIcon, - JS: isLight ? JavaScriptIcon : JavaScriptIcon, - JavaScript: isLight ? JavaScriptIcon : JavaScriptIcon, - Python: isLight ? PythonIcon : PythonIcon, - PY: isLight ? PythonIcon : PythonIcon, - Java: isLight ? JavaIcon : JavaIcon, - CPP: isLight ? CppIcon : CppIcon, - CMake: isLight ? CMakeIcon : CMakeIcon, - '^c$': isLight ? CIcon : CIcon, - csharp: isLight ? CSharpIcon : CSharpIcon, - Go: isLight ? GoIcon : GoIcon, - Json: isLight ? JsonIcon : JsonIcon, - Rust: isLight ? RustIcon : RustIcon, - Yaml: isLight ? YamlIcon : YamlIcon, - Php: isLight ? PhpIcon : PhpIcon, - Ruby: isLight ? RubyIcon : RubyIcon, - Lua: isLight ? LuaIcon : LuaIcon, - CSS: isLight ? CSS3Icon : CSS3Icon, - CSS3: isLight ? CSS3Icon : CSS3Icon, - XML: isLight ? XMLIcon : XMLIcon, - vb: isLight ? VBIcon : VBIcon, - visualbasic: isLight ? VBIcon : VBIcon, - HTML: isLight ? XMLIcon : XMLIcon + bash: BashIcon, + cpp: CppIcon, + cmake: CMakeIcon, + css: CSS3Icon, + css3: CSS3Icon, + '^c$': CIcon, + '^cs$': CSharpIcon, + csharp: CSharpIcon, + go: GoIcon, + lua: LuaIcon, + js: JavaScriptIcon, + javascript: JavaScriptIcon, + java: JavaIcon, + json: JsonIcon, + python: PythonIcon, + py: PythonIcon, + perl: PerlIcon, + php: PhpIcon, + rs: RustIcon, + rust: RustIcon, + ts: TypeScriptIcon, + typescript: TypeScriptIcon, + yml: YamlIcon, + yaml: YamlIcon, + ruby: RubyIcon, + vb: VBIcon, + visualbasic: VBIcon, + xml: XMLIcon } for (const key in logoMap) { From 171f9e02136f29cc7cf9ef04db8d037690fe06e3 Mon Sep 17 00:00:00 2001 From: imoyy Date: Sat, 6 Sep 2025 13:47:11 +0800 Subject: [PATCH 4/4] change `C` icon to a better one --- src/renderer/src/assets/images/lang/c.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/src/assets/images/lang/c.svg b/src/renderer/src/assets/images/lang/c.svg index 740ffd822..c9afdbd14 100644 --- a/src/renderer/src/assets/images/lang/c.svg +++ b/src/renderer/src/assets/images/lang/c.svg @@ -1 +1 @@ - +