diff --git a/lib/shared/widgets/markdown/markdown_config.dart b/lib/shared/widgets/markdown/markdown_config.dart index 40acd50..9642bd4 100644 --- a/lib/shared/widgets/markdown/markdown_config.dart +++ b/lib/shared/widgets/markdown/markdown_config.dart @@ -5,6 +5,9 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_highlight/flutter_highlight.dart'; +import 'package:flutter_highlight/themes/atom-one-dark.dart'; +import 'package:flutter_highlight/themes/github.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_math_fork/flutter_math.dart'; import 'package:gpt_markdown/gpt_markdown.dart'; @@ -98,7 +101,13 @@ class ConduitMarkdown { ? 'plaintext' : language.trim(); - // Match GitHub/Atom theme colors for code block container + // Map common language aliases to highlight.js recognized names + final highlightLanguage = _mapLanguage(normalizedLanguage); + + // Use Atom One Dark for dark mode, GitHub for light mode + final highlightTheme = isDark ? atomOneDarkTheme : githubTheme; + + // Match theme colors for code block container final codeBackground = isDark ? const Color(0xFF282c34) // Atom One Dark background : const Color(0xFFfafbfc); // GitHub light background @@ -135,10 +144,12 @@ class ConduitMarkdown { SingleChildScrollView( scrollDirection: Axis.horizontal, padding: const EdgeInsets.all(Spacing.md), - child: SelectableText( + child: HighlightView( code, - style: AppTypography.codeStyle.copyWith( - color: theme.codeText, + language: highlightLanguage, + theme: highlightTheme, + padding: EdgeInsets.zero, + textStyle: AppTypography.codeStyle.copyWith( fontFamily: AppTypography.monospaceFontFamily, ), ), @@ -148,6 +159,34 @@ class ConduitMarkdown { ); } + /// Maps common language names/aliases to highlight.js recognized names. + static String _mapLanguage(String language) { + final lower = language.toLowerCase(); + + // Common language aliases mapping + const languageMap = { + 'js': 'javascript', + 'ts': 'typescript', + 'py': 'python', + 'rb': 'ruby', + 'sh': 'bash', + 'shell': 'bash', + 'zsh': 'bash', + 'yml': 'yaml', + 'dockerfile': 'docker', + 'kt': 'kotlin', + 'cs': 'csharp', + 'c++': 'cpp', + 'objc': 'objectivec', + 'objective-c': 'objectivec', + 'txt': 'plaintext', + 'text': 'plaintext', + 'md': 'markdown', + }; + + return languageMap[lower] ?? lower; + } + static Widget _buildImage( BuildContext context, Uri uri, diff --git a/pubspec.lock b/pubspec.lock index 407e771..627087a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -494,6 +494,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" + flutter_highlight: + dependency: "direct main" + description: + name: flutter_highlight + sha256: "7b96333867aa07e122e245c033b8ad622e4e3a42a1a2372cbb098a2541d8782c" + url: "https://pub.dev" + source: hosted + version: "0.7.0" flutter_lints: dependency: "direct dev" description: @@ -709,6 +717,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + highlight: + dependency: transitive + description: + name: highlight + sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21" + url: "https://pub.dev" + source: hosted + version: "0.7.0" hive_ce: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 2de3fbb..fedaaf6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -78,6 +78,7 @@ dependencies: flutter_svg: ^2.2.3 html_unescape: ^2.0.0 home_widget: ^0.8.1 + flutter_highlight: ^0.7.0 # Clipboard functionality is available through flutter/services (part of Flutter SDK)