diff --git a/index.html b/index.html
index 42a3630..c84f4e0 100644
--- a/index.html
+++ b/index.html
@@ -5,6 +5,10 @@
Code Canvas - Create Beautiful Code Images
+
+
+
+
diff --git a/src/store/canvasStore.ts b/src/store/canvasStore.ts
index fde5d58..8f19c1b 100644
--- a/src/store/canvasStore.ts
+++ b/src/store/canvasStore.ts
@@ -235,9 +235,15 @@ export const createCodeElement = (x: number, y: number): CodeElement => ({
locked: false,
visible: true,
props: {
- code: '// Your code here\nconsole.log("Hello, World!");',
- language: 'javascript',
- theme: 'github-dark',
+ code: `@Composable
+fun Greeting(name: String) {
+ Text(
+ text = "Hello, $name!",
+ modifier = Modifier.padding(16.dp)
+ )
+}`,
+ language: 'kotlin',
+ theme: 'dracula',
fontFamily: 'JetBrains Mono',
fontSize: 14,
lineHeight: 1.5,
diff --git a/src/types/index.ts b/src/types/index.ts
index 63ef467..49d639d 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -125,44 +125,58 @@ export const ASPECT_RATIOS: AspectRatio[] = [
];
export const CODE_THEMES = [
- { id: 'github-dark', name: 'GitHub Dark', bg: '#0d1117' },
- { id: 'github-light', name: 'GitHub Light', bg: '#ffffff' },
+ // IntelliJ / Android Studio themes (prioritized for Kotlin)
+ { id: 'andromeeda', name: 'Andromeeda', bg: '#23262e' },
+ { id: 'aurora-x', name: 'Aurora X', bg: '#07090f' },
+ { id: 'dark-plus', name: 'Dark+ (VS Code)', bg: '#1e1e1e' },
{ id: 'dracula', name: 'Dracula', bg: '#282a36' },
- { id: 'nord', name: 'Nord', bg: '#2e3440' },
- { id: 'one-dark-pro', name: 'One Dark Pro', bg: '#282c34' },
- { id: 'monokai', name: 'Monokai', bg: '#272822' },
- { id: 'tokyo-night', name: 'Tokyo Night', bg: '#1a1b26' },
- { id: 'vitesse-dark', name: 'Vitesse Dark', bg: '#121212' },
- { id: 'vitesse-light', name: 'Vitesse Light', bg: '#ffffff' },
+ { id: 'dracula-soft', name: 'Dracula Soft', bg: '#282a36' },
+ { id: 'github-dark', name: 'GitHub Dark', bg: '#0d1117' },
+ { id: 'github-dark-dimmed', name: 'GitHub Dimmed', bg: '#22272e' },
+ { id: 'github-light', name: 'GitHub Light', bg: '#ffffff' },
+ { id: 'light-plus', name: 'Light+ (VS Code)', bg: '#ffffff' },
{ id: 'material-theme-darker', name: 'Material Darker', bg: '#212121' },
- { id: 'catppuccin-mocha', name: 'Catppuccin Mocha', bg: '#1e1e2e' },
- { id: 'catppuccin-latte', name: 'Catppuccin Latte', bg: '#eff1f5' },
- { id: 'slack-dark', name: 'Slack Dark', bg: '#222222' },
- { id: 'poimandres', name: 'Poimandres', bg: '#1b1e28' },
- { id: 'night-owl', name: 'Night Owl', bg: '#011627' },
+ { id: 'material-theme-ocean', name: 'Material Ocean', bg: '#0f111a' },
+ { id: 'material-theme-palenight', name: 'Material Palenight', bg: '#292d3e' },
{ id: 'min-dark', name: 'Min Dark', bg: '#1f1f1f' },
{ id: 'min-light', name: 'Min Light', bg: '#ffffff' },
- { id: 'ayu-dark', name: 'Ayu Dark', bg: '#0b0e14' },
+ { id: 'monokai', name: 'Monokai', bg: '#272822' },
+ { id: 'night-owl', name: 'Night Owl', bg: '#011627' },
+ { id: 'nord', name: 'Nord', bg: '#2e3440' },
+ { id: 'one-dark-pro', name: 'One Dark Pro', bg: '#282c34' },
+ { id: 'poimandres', name: 'Poimandres', bg: '#1b1e28' },
+ { id: 'rose-pine', name: 'Rosé Pine', bg: '#191724' },
+ { id: 'rose-pine-moon', name: 'Rosé Pine Moon', bg: '#232136' },
+ { id: 'slack-dark', name: 'Slack Dark', bg: '#222222' },
{ id: 'solarized-dark', name: 'Solarized Dark', bg: '#002b36' },
{ id: 'solarized-light', name: 'Solarized Light', bg: '#fdf6e3' },
+ { id: 'tokyo-night', name: 'Tokyo Night', bg: '#1a1b26' },
+ { id: 'vesper', name: 'Vesper', bg: '#101010' },
+ { id: 'vitesse-dark', name: 'Vitesse Dark', bg: '#121212' },
+ { id: 'vitesse-light', name: 'Vitesse Light', bg: '#ffffff' },
] as const;
export type CodeThemeId = typeof CODE_THEMES[number]['id'];
export const LANGUAGES = [
- 'javascript',
- 'typescript',
'kotlin',
'java',
+ 'typescript',
+ 'javascript',
'python',
'rust',
'go',
+ 'swift',
+ 'dart',
'html',
'css',
'json',
+ 'xml',
+ 'yaml',
'markdown',
'bash',
'sql',
+ 'groovy',
] as const;
export const FONT_FAMILIES = {
diff --git a/src/utils/highlighter.ts b/src/utils/highlighter.ts
index 6f8a7f1..8fad2c5 100644
--- a/src/utils/highlighter.ts
+++ b/src/utils/highlighter.ts
@@ -62,7 +62,7 @@ export function getThemeBackground(themeId: CodeThemeId): string {
}
export function isLightTheme(themeId: CodeThemeId): boolean {
- const lightThemes = ['github-light', 'vitesse-light', 'catppuccin-latte', 'min-light', 'solarized-light'];
+ const lightThemes = ['github-light', 'vitesse-light', 'min-light', 'solarized-light', 'light-plus'];
return lightThemes.includes(themeId);
}
@@ -81,6 +81,22 @@ export function isHighlighterReady(): boolean {
// Language detection based on common patterns
export function detectLanguage(code: string): string {
+ // Kotlin / Jetpack Compose patterns (check first - primary language)
+ // Look for @Composable, fun, val, var, class, object, companion object, etc.
+ if (/@Composable|@Preview|@OptIn|@Suppress/.test(code)) {
+ return 'kotlin';
+ }
+ if (/^(fun|val|var|class|object|package|import|sealed|data\s+class|enum\s+class|interface)\s+/m.test(code)) {
+ // Check for Kotlin-specific syntax
+ if (/:\s*\w+(\s*[={()]|$|\s*,)/.test(code) ||
+ /\b(Unit|String|Int|Long|Boolean|Float|Double|List|Map|Set|suspend|inline|crossinline|noinline|reified)\b/.test(code) ||
+ /\bModifier\b|\bColumn\b|\bRow\b|\bBox\b|\bText\b|\bButton\b|\bScaffold\b/.test(code) ||
+ /\.copy\(|\.let\s*\{|\.apply\s*\{|\.also\s*\{|\.run\s*\{/.test(code) ||
+ /\blambda\b|->/.test(code)) {
+ return 'kotlin';
+ }
+ }
+
// TypeScript/JavaScript patterns
if (/^import\s+.*from\s+['"]|^export\s+(default\s+)?|const\s+\w+:\s*\w+/m.test(code)) {
if (/:\s*(string|number|boolean|any|void|Promise|Array)\b/.test(code)) {
@@ -89,15 +105,22 @@ export function detectLanguage(code: string): string {
return 'javascript';
}
- // Kotlin patterns
- if (/^(fun|val|var|class|object|package|import)\s+/m.test(code) &&
- /:\s*\w+(\s*=|\s*\{|\s*\))/.test(code)) {
- return 'kotlin';
+ // Java patterns (after Kotlin to avoid false positives)
+ if (/^(public|private|protected)\s+(static\s+)?(class|void|int|String)/m.test(code) &&
+ !/@Composable/.test(code)) {
+ return 'java';
}
- // Java patterns
- if (/^(public|private|protected)\s+(static\s+)?(class|void|int|String)/m.test(code)) {
- return 'java';
+ // Swift patterns
+ if (/^(func|var|let|class|struct|enum|protocol|import\s+\w+)\s+/m.test(code) &&
+ /@State|@Binding|@Published|@ObservedObject|some\s+View/.test(code)) {
+ return 'swift';
+ }
+
+ // Dart/Flutter patterns
+ if (/^(class|void|final|const|import\s+')/m.test(code) &&
+ /Widget|StatelessWidget|StatefulWidget|BuildContext|setState/.test(code)) {
+ return 'dart';
}
// Python patterns
@@ -115,6 +138,17 @@ export function detectLanguage(code: string): string {
return 'go';
}
+ // Groovy/Gradle patterns
+ if (/^(plugins|dependencies|android|buildscript)\s*\{/m.test(code) ||
+ /implementation\s*\(|compile\s*\(/.test(code)) {
+ return 'groovy';
+ }
+
+ // XML patterns (for Android layouts)
+ if (/^<\?xml|^