\ No newline at end of file
diff --git a/src/components/OutputPanel.vue b/src/components/OutputPanel.vue
index fc79782..b40ccea 100644
--- a/src/components/OutputPanel.vue
+++ b/src/components/OutputPanel.vue
@@ -3,11 +3,23 @@
+
没有输出
可以尝试运行一些代码
@@ -31,12 +43,55 @@
\ No newline at end of file
diff --git a/src/components/StatusBar.vue b/src/components/StatusBar.vue
index 4d2c965..83e6ce6 100644
--- a/src/components/StatusBar.vue
+++ b/src/components/StatusBar.vue
@@ -6,7 +6,7 @@
-
{{ envInfo.installed ? `${ envInfo.language }: ${ envInfo.version }` : `${ envInfo.language } 环境未安装` }}
+
{{ envInfo.installed ? `${ envInfo.language }: ${ envInfo.version }` : `${ envInfo.language }: 环境未安装` }}
diff --git a/src/utils/highlighter/index.ts b/src/utils/highlighter/index.ts
new file mode 100644
index 0000000..de2c173
--- /dev/null
+++ b/src/utils/highlighter/index.ts
@@ -0,0 +1,37 @@
+export * from './types'
+export * from './manager'
+export { Python2Highlighter } from './languages/python2'
+export { Python3Highlighter } from './languages/python3'
+
+// 导入并重新导出管理器实例
+import { HighlightManager } from './manager'
+
+// 创建单例实例
+export const highlightManager = new HighlightManager()
+
+/**
+ * 高亮代码的便捷函数
+ * @param code 源代码
+ * @param language 语言名称
+ * @returns 高亮后的 HTML
+ */
+export function highlightCode(code: string, language: string): string
+{
+ return highlightManager.highlight(code, language)
+}
+
+/**
+ * 获取支持的语言列表
+ */
+export function getSupportedLanguages()
+{
+ return highlightManager.getSupportedLanguages()
+}
+
+/**
+ * 注册自定义高亮器
+ */
+export function registerHighlighter(highlighter: import('./types').LanguageHighlighter)
+{
+ highlightManager.register(highlighter)
+}
\ No newline at end of file
diff --git a/src/utils/highlighter/languages/python2.ts b/src/utils/highlighter/languages/python2.ts
new file mode 100644
index 0000000..a1cbf2e
--- /dev/null
+++ b/src/utils/highlighter/languages/python2.ts
@@ -0,0 +1,94 @@
+import type { HighlightRule, LanguageHighlighter } from '../types'
+
+export class Python2Highlighter
+ implements LanguageHighlighter
+{
+ getLanguageName(): string
+ {
+ return 'python2'
+ }
+
+ getDisplayName(): string
+ {
+ return 'Python 2'
+ }
+
+ getOrder(): number
+ {
+ return 2
+ }
+
+ getRules(): HighlightRule[]
+ {
+ return [
+ // 1. 注释 (最高优先级)
+ {
+ pattern: /#.*$/gm,
+ className: 'text-gray-500 italic',
+ priority: 1
+ },
+
+ // 2. 字符串 (高优先级)
+ {
+ pattern: /"""[\s\S]*?"""/g,
+ className: 'text-green-600',
+ priority: 2
+ },
+ {
+ pattern: /'''[\s\S]*?'''/g,
+ className: 'text-green-600',
+ priority: 2
+ },
+ {
+ pattern: /"(?:[^"\\]|\\.)*"/g,
+ className: 'text-green-600',
+ priority: 2
+ },
+ {
+ pattern: /'(?:[^'\\]|\\.)*'/g,
+ className: 'text-green-600',
+ priority: 2
+ },
+
+ // 3. Python 2 关键字
+ {
+ pattern: /\b(def|class|if|elif|else|for|while|try|except|finally|with|as|import|from|return|yield|break|continue|pass|lambda|and|or|not|in|is|True|False|None|print|exec|raw_input)\b/g,
+ className: 'text-purple-600 font-semibold',
+ priority: 3
+ },
+
+ // 4. 数字
+ {
+ pattern: /\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b/g,
+ className: 'text-blue-600',
+ priority: 4
+ },
+
+ // 5. 函数调用
+ {
+ pattern: /\b([a-zA-Z_]\w*)(?=\s*\()/g,
+ className: 'text-orange-600',
+ priority: 5
+ },
+
+ // 6. 类名定义
+ {
+ pattern: /\bclass\s+([A-Z]\w*)/g,
+ className: 'text-yellow-600 font-semibold',
+ priority: 6
+ }
+ ]
+ }
+
+ preProcess(code: string): string
+ {
+ // Python 2 特定的预处理
+ return code
+ }
+
+ postProcess(highlighted: string): string
+ {
+ // Python 2 特定的后处理
+ return highlighted
+ }
+}
\ No newline at end of file
diff --git a/src/utils/highlighter/languages/python3.ts b/src/utils/highlighter/languages/python3.ts
new file mode 100644
index 0000000..d6f83ed
--- /dev/null
+++ b/src/utils/highlighter/languages/python3.ts
@@ -0,0 +1,111 @@
+import type { HighlightRule, LanguageHighlighter } from '../types'
+
+export class Python3Highlighter
+ implements LanguageHighlighter
+{
+ getLanguageName(): string
+ {
+ return 'python3'
+ }
+
+ getDisplayName(): string
+ {
+ return 'Python 3'
+ }
+
+ getOrder(): number
+ {
+ return 1
+ }
+
+ getRules(): HighlightRule[]
+ {
+ return [
+ // 1. 注释 (最高优先级)
+ {
+ pattern: /#.*$/gm,
+ className: 'text-gray-500 italic',
+ priority: 1
+ },
+
+ // 2. 字符串 (高优先级)
+ {
+ pattern: /"""[\s\S]*?"""/g,
+ className: 'text-green-600',
+ priority: 2
+ },
+ {
+ pattern: /'''[\s\S]*?'''/g,
+ className: 'text-green-600',
+ priority: 2
+ },
+ {
+ pattern: /f"(?:[^"\\]|\\.)*"/g,
+ className: 'text-emerald-600',
+ priority: 2
+ }, // f-strings
+ {
+ pattern: /f'(?:[^'\\]|\\.)*'/g,
+ className: 'text-emerald-600',
+ priority: 2
+ }, // f-strings
+ {
+ pattern: /"(?:[^"\\]|\\.)*"/g,
+ className: 'text-green-600',
+ priority: 2
+ },
+ {
+ pattern: /'(?:[^'\\]|\\.)*'/g,
+ className: 'text-green-600',
+ priority: 2
+ },
+
+ // 3. Python 3 关键字
+ {
+ pattern: /\b(def|class|if|elif|else|for|while|try|except|finally|with|as|import|from|return|yield|break|continue|pass|lambda|and|or|not|in|is|True|False|None|async|await|nonlocal)\b/g,
+ className: 'text-purple-600 font-semibold',
+ priority: 3
+ },
+
+ // 4. 数字
+ {
+ pattern: /\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b/g,
+ className: 'text-blue-600',
+ priority: 4
+ },
+
+ // 5. 函数调用
+ {
+ pattern: /\b([a-zA-Z_]\w*)(?=\s*\()/g,
+ className: 'text-orange-600',
+ priority: 5
+ },
+
+ // 6. 装饰器
+ {
+ pattern: /@[a-zA-Z_]\w*/g,
+ className: 'text-yellow-600',
+ priority: 6
+ },
+
+ // 7. 类名定义
+ {
+ pattern: /\bclass\s+([A-Z]\w*)/g,
+ className: 'text-yellow-600 font-semibold',
+ priority: 7
+ }
+ ]
+ }
+
+ preProcess(code: string): string
+ {
+ // Python 3 特定的预处理
+ return code
+ }
+
+ postProcess(highlighted: string): string
+ {
+ // Python 3 特定的后处理
+ return highlighted
+ }
+}
\ No newline at end of file
diff --git a/src/utils/highlighter/manager.ts b/src/utils/highlighter/manager.ts
new file mode 100644
index 0000000..9cc4105
--- /dev/null
+++ b/src/utils/highlighter/manager.ts
@@ -0,0 +1,180 @@
+import type { HighlightMatch, LanguageHighlighter } from './types'
+import { Python2Highlighter } from './languages/python2'
+import { Python3Highlighter } from './languages/python3'
+
+export class HighlightManager
+{
+ private highlighters = new Map()
+
+ constructor()
+ {
+ this.registerDefaultHighlighters()
+ }
+
+ /**
+ * 注册默认高亮器
+ */
+ private registerDefaultHighlighters(): void
+ {
+ this.register(new Python2Highlighter())
+ this.register(new Python3Highlighter())
+ }
+
+ /**
+ * 注册高亮器
+ */
+ register(highlighter: LanguageHighlighter): void
+ {
+ this.highlighters.set(highlighter.getLanguageName(), highlighter)
+ }
+
+ /**
+ * 注销高亮器
+ */
+ unregister(languageName: string): boolean
+ {
+ return this.highlighters.delete(languageName)
+ }
+
+ /**
+ * 获取高亮器
+ */
+ getHighlighter(languageName: string): LanguageHighlighter | undefined
+ {
+ return this.highlighters.get(languageName)
+ }
+
+ /**
+ * 获取支持的语言列表
+ */
+ getSupportedLanguages(): Array<{ name: string; displayName: string; order: number }>
+ {
+ const languages = Array.from(this.highlighters.values())
+ .map(highlighter => ({
+ name: highlighter.getLanguageName(),
+ displayName: highlighter.getDisplayName(),
+ order: highlighter.getOrder()
+ }))
+
+ // 按 order 排序
+ return languages.sort((a, b) => a.order - b.order)
+ }
+
+ /**
+ * 检查是否支持某种语言
+ */
+ isSupported(languageName: string): boolean
+ {
+ return this.highlighters.has(languageName)
+ }
+
+ /**
+ * 对代码进行语法高亮
+ */
+ highlight(code: string, languageName: string): string
+ {
+ if (!code) {
+ return ''
+ }
+
+ const highlighter = this.getHighlighter(languageName)
+ if (!highlighter) {
+ // 如果不支持该语言,返回转义后的原始代码
+ return this.escapeHtml(code)
+ }
+
+ // 预处理
+ let processedCode = highlighter.preProcess ? highlighter.preProcess(code) : code
+
+ // HTML 转义
+ processedCode = this.escapeHtml(processedCode)
+
+ // 应用高亮规则
+ const highlighted = this.applyHighlightRules(processedCode, highlighter.getRules())
+
+ // 后处理
+ return highlighter.postProcess ? highlighter.postProcess(highlighted) : highlighted
+ }
+
+ /**
+ * 应用高亮规则
+ */
+ private applyHighlightRules(code: string, rules: Array<{ pattern: RegExp; className: string; priority?: number }>): string
+ {
+ // 收集所有匹配
+ const matches: HighlightMatch[] = []
+
+ for (const rule of rules) {
+ const regex = new RegExp(rule.pattern.source, rule.pattern.flags)
+ let match
+
+ while ((match = regex.exec(code)) !== null) {
+ matches.push({
+ start: match.index,
+ end: match.index + match[0].length,
+ className: rule.className,
+ priority: rule.priority || 999
+ })
+
+ // 防止无限循环
+ if (!rule.pattern.global) {
+ break
+ }
+ }
+ }
+
+ // 按优先级排序,优先级高的(数字小的)在前
+ matches.sort((a, b) => a.priority - b.priority || a.start - b.start)
+
+ // 移除重叠的匹配(保留高优先级的)
+ const filteredMatches = this.removeOverlappingMatches(matches)
+
+ // 按开始位置倒序排序,从后往前插入标签
+ filteredMatches.sort((a, b) => b.start - a.start)
+
+ // 插入高亮标签
+ let highlighted = code
+ for (const match of filteredMatches) {
+ const before = highlighted.substring(0, match.start)
+ const content = highlighted.substring(match.start, match.end)
+ const after = highlighted.substring(match.end)
+
+ highlighted = before + `${ content }` + after
+ }
+
+ return highlighted
+ }
+
+ /**
+ * 移除重叠的匹配
+ */
+ private removeOverlappingMatches(matches: HighlightMatch[]): HighlightMatch[]
+ {
+ const filteredMatches: HighlightMatch[] = []
+
+ for (const match of matches) {
+ const hasOverlap = filteredMatches.some(existing =>
+ (match.start < existing.end && match.end > existing.start)
+ )
+
+ if (!hasOverlap) {
+ filteredMatches.push(match)
+ }
+ }
+
+ return filteredMatches
+ }
+
+ /**
+ * HTML 转义
+ */
+ private escapeHtml(text: string): string
+ {
+ return text
+ // .replace(/&/g, '&')
+ .replace(//g, '>')
+ // .replace(/"/g, '"')
+ // .replace(/'/g, ''')
+ }
+}
diff --git a/src/utils/highlighter/types.ts b/src/utils/highlighter/types.ts
new file mode 100644
index 0000000..41fe98d
--- /dev/null
+++ b/src/utils/highlighter/types.ts
@@ -0,0 +1,50 @@
+// 语法高亮规则接口
+export interface HighlightRule
+{
+ pattern: RegExp
+ className: string
+ priority?: number
+}
+
+// 匹配结果接口
+export interface HighlightMatch
+{
+ start: number
+ end: number
+ className: string
+ priority: number
+}
+
+// 语言高亮插件接口
+export interface LanguageHighlighter
+{
+ /**
+ * 获取语言名称
+ */
+ getLanguageName(): string
+
+ /**
+ * 获取显示名称
+ */
+ getDisplayName(): string
+
+ /**
+ * 获取高亮规则
+ */
+ getRules(): HighlightRule[]
+
+ /**
+ * 获取排序权重(数字越小越靠前)
+ */
+ getOrder(): number
+
+ /**
+ * 预处理代码(可选)
+ */
+ preProcess?(code: string): string
+
+ /**
+ * 后处理高亮结果(可选)
+ */
+ postProcess?(highlighted: string): string
+}
\ No newline at end of file