feat(desktop): custom syntax colors

This commit is contained in:
Adam
2025-11-07 12:48:12 -06:00
parent 4463d319c9
commit 3a1d1a6284
9 changed files with 1622 additions and 3591 deletions

View File

@@ -188,7 +188,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
async sync(sessionID: string, _isRetry = false) { async sync(sessionID: string, _isRetry = false) {
const [session, messages, todo, diff] = await Promise.all([ const [session, messages, todo, diff] = await Promise.all([
sdk.client.session.get({ path: { id: sessionID }, throwOnError: true }), sdk.client.session.get({ path: { id: sessionID }, throwOnError: true }),
sdk.client.session.messages({ path: { id: sessionID } }), sdk.client.session.messages({ path: { id: sessionID }, query: { limit: 100 } }),
sdk.client.session.todo({ path: { id: sessionID } }), sdk.client.session.todo({ path: { id: sessionID } }),
sdk.client.session.diff({ path: { id: sessionID } }), sdk.client.session.diff({ path: { id: sessionID } }),
]) ])
@@ -211,12 +211,6 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
draft.session_diff[sessionID] = diff.data ?? [] draft.session_diff[sessionID] = diff.data ?? []
}), }),
) )
// If no messages and this might be a new session, retry after a delay
// if (!isRetry && messages.data!.length === 0) {
// setTimeout(() => this.sync(sessionID, true), 500)
// return
// }
}, },
fetch: async (count = 10) => { fetch: async (count = 10) => {
setStore("limit", (x) => x + count) setStore("limit", (x) => x + count)

View File

@@ -736,7 +736,7 @@ export default function Page() {
"relative px-6 py-2 w-full flex flex-col gap-6 flex-1 min-h-0": true, "relative px-6 py-2 w-full flex flex-col gap-6 flex-1 min-h-0": true,
}} }}
> >
<div class="h-8 w-full flex items-center justify-between shrink-0 self-stretch sticky top-0 bg-background-strong z-100"> <div class="h-8 w-full flex items-center justify-between shrink-0 self-stretch sticky top-0 bg-background-stronger z-100">
<div class="flex items-center gap-x-3"></div> <div class="flex items-center gap-x-3"></div>
</div> </div>
<div class="text-14-medium text-text-strong">All changes</div> <div class="text-14-medium text-text-strong">All changes</div>
@@ -766,6 +766,7 @@ export default function Page() {
</Accordion.Header> </Accordion.Header>
<Accordion.Content> <Accordion.Content>
<Diff <Diff
diffStyle="split"
before={{ before={{
name: diff.file!, name: diff.file!,
contents: diff.before!, contents: diff.before!,

View File

@@ -14,7 +14,8 @@ export function Code<T>(props: CodeProps<T>) {
createEffect(() => { createEffect(() => {
const instance = new File<T>({ const instance = new File<T>({
theme: { dark: "oc-1-dark", light: "oc-1-light" }, // or any Shiki theme theme: { dark: "oc-1-dark", light: "oc-1-light" },
// theme: { dark: "pierre-dark", light: "pierre-light" },
overflow: "wrap", // or 'scroll' overflow: "wrap", // or 'scroll'
themeType: "system", // 'system', 'light', or 'dark' themeType: "system", // 'system', 'light', or 'dark'
disableFileHeader: true, disableFileHeader: true,

File diff suppressed because it is too large Load Diff

View File

@@ -196,15 +196,20 @@
--color-icon-diff-delete-base: var(--icon-diff-delete-base); --color-icon-diff-delete-base: var(--icon-diff-delete-base);
--color-icon-diff-delete-hover: var(--icon-diff-delete-hover); --color-icon-diff-delete-hover: var(--icon-diff-delete-hover);
--color-syntax-comment: var(--syntax-comment); --color-syntax-comment: var(--syntax-comment);
--color-syntax-regexp: var(--syntax-regexp);
--color-syntax-string: var(--syntax-string); --color-syntax-string: var(--syntax-string);
--color-syntax-keyword: var(--syntax-keyword); --color-syntax-keyword: var(--syntax-keyword);
--color-syntax-function: var(--syntax-function); --color-syntax-function: var(--syntax-function);
--color-syntax-number: var(--syntax-number); --color-syntax-number: var(--syntax-number);
--color-syntax-operator: var(--syntax-operator); --color-syntax-operator: var(--syntax-operator);
--color-syntax-variable: var(--syntax-variable); --color-syntax-variable: var(--syntax-variable);
--color-syntax-property: var(--syntax-property);
--color-syntax-parameter: var(--syntax-parameter);
--color-syntax-type: var(--syntax-type); --color-syntax-type: var(--syntax-type);
--color-syntax-constant: var(--syntax-constant); --color-syntax-constant: var(--syntax-constant);
--color-syntax-punctuation: var(--syntax-punctuation); --color-syntax-punctuation: var(--syntax-punctuation);
--color-syntax-namespace: var(--syntax-namespace);
--color-syntax-enum: var(--syntax-enum);
--color-syntax-success: var(--syntax-success); --color-syntax-success: var(--syntax-success);
--color-syntax-warning: var(--syntax-warning); --color-syntax-warning: var(--syntax-warning);
--color-syntax-critical: var(--syntax-critical); --color-syntax-critical: var(--syntax-critical);

View File

@@ -268,20 +268,25 @@
--icon-diff-add-active: var(--mint-light-12); --icon-diff-add-active: var(--mint-light-12);
--icon-diff-delete-base: var(--ember-light-10); --icon-diff-delete-base: var(--ember-light-10);
--icon-diff-delete-hover: var(--ember-light-11); --icon-diff-delete-hover: var(--ember-light-11);
--syntax-comment: #8a8a8a; --syntax-comment: var(--text-weaker);
--syntax-string: #d68c27; --syntax-regexp: var(--text-base);
--syntax-keyword: #3b7dd8; --syntax-string: var(--mint-light-11);
--syntax-function: #d1383d; --syntax-keyword: var(--text-weak);
--syntax-number: #3d9a57; --syntax-primitive: var(--ember-light-11);
--syntax-operator: #d68c27; --syntax-operator: var(--text-weak);
--syntax-variable: #b0851f; --syntax-variable: var(--text-strong);
--syntax-type: #318795; --syntax-property: var(--lilac-light-11);
--syntax-constant: #953170; --syntax-type: var(--cobalt-light-11);
--syntax-punctuation: #1a1a1a; --syntax-constant: var(--lilac-light-11);
--syntax-success: var(--apple-dark-10); --syntax-punctuation: var(--text-weak);
--syntax-object: var(--blue-light-11);
--syntax-success: var(--apple-light-10);
--syntax-warning: var(--amber-light-10); --syntax-warning: var(--amber-light-10);
--syntax-critical: var(--ember-dark-9); --syntax-critical: var(--ember-light-9);
--syntax-info: var(--lilac-dark-11); --syntax-info: var(--lilac-light-11);
--syntax-diff-add: var(--mint-light-11);
--syntax-diff-delete: var(--ember-light-11);
--syntax-unknown: red;
--markdown-heading: #d68c27; --markdown-heading: #d68c27;
--markdown-text: #1a1a1a; --markdown-text: #1a1a1a;
--markdown-link: #3b7dd8; --markdown-link: #3b7dd8;
@@ -503,20 +508,24 @@
--icon-diff-add-active: var(--mint-dark-11); --icon-diff-add-active: var(--mint-dark-11);
--icon-diff-delete-base: var(--ember-dark-9); --icon-diff-delete-base: var(--ember-dark-9);
--icon-diff-delete-hover: var(--ember-dark-10); --icon-diff-delete-hover: var(--ember-dark-10);
--syntax-comment: #808080; --syntax-comment: var(--text-weaker);
--syntax-string: #9d7cd8; --syntax-regexp: var(--text-base);
--syntax-keyword: #fab283; --syntax-string: var(--mint-dark-11);
--syntax-function: #e06c75; --syntax-keyword: var(--text-weak);
--syntax-number: #7fd88f; --syntax-primitive: var(--ember-dark-11);
--syntax-operator: #f5a742; --syntax-operator: var(--text-weak);
--syntax-variable: #e5c07b; --syntax-variable: var(--text-strong);
--syntax-type: #56b6c2; --syntax-property: var(--lilac-dark-11);
--syntax-constant: #c2569a; --syntax-type: var(--cobalt-dark-11);
--syntax-punctuation: #eeeeee; --syntax-constant: var(--lilac-dark-11);
--syntax-punctuation: var(--text-weak);
--syntax-object: var(--blue-dark-11);
--syntax-success: var(--apple-dark-10); --syntax-success: var(--apple-dark-10);
--syntax-warning: var(--amber-dark-10); --syntax-warning: var(--amber-dark-10);
--syntax-critical: var(--ember-dark-10); --syntax-critical: var(--ember-dark-9);
--syntax-info: var(--lilac-dark-10); --syntax-info: var(--lilac-dark-11);
--syntax-diff-add: var(--mint-dark-11);
--syntax-diff-delete: var(--ember-dark-11);
--markdown-heading: #9d7cd8; --markdown-heading: #9d7cd8;
--markdown-text: #eeeeee; --markdown-text: #eeeeee;
--markdown-link: #fab283; --markdown-link: #fab283;

461
theme-test.java Normal file
View File

@@ -0,0 +1,461 @@
package com.example.theme;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.stream.*;
import java.time.*;
import java.time.format.*;
import java.net.*;
import java.io.*;
import java.nio.file.*;
import java.sql.*;
import java.lang.annotation.*;
import java.math.BigDecimal;
import java.math.BigInteger;
// Enum definition
public enum LogLevel {
DEBUG(0, "Debug"),
INFO(1, "Info"),
WARN(2, "Warning"),
ERROR(3, "Error");
private final int level;
private final String description;
LogLevel(int level, String description) {
this.level = level;
this.description = description;
}
public int getLevel() { return level; }
public String getDescription() { return description; }
}
// Interface with generics
public interface Repository<T extends Entity> {
Optional<T> findById(Long id);
List<T> findAll();
T save(T entity);
void delete(Long id);
Stream<T> stream();
@FunctionalInterface
interface Predicate<T> {
boolean test(T t);
}
}
// Abstract class
public abstract class AbstractService<T extends Entity> implements Repository<T> {
protected final Map<Long, T> cache = new ConcurrentHashMap<>();
protected volatile boolean initialized = false;
@Override
public Optional<T> findById(Long id) {
return Optional.ofNullable(cache.get(id));
}
@Override
public List<T> findAll() {
return new ArrayList<>(cache.values());
}
@Override
public Stream<T> stream() {
return cache.values().stream();
}
protected abstract void validate(T entity) throws ValidationException;
}
// Annotation definition
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Service {
String value() default "";
boolean transactional() default true;
Class<?>[] exceptions() = {};
}
// Record class (Java 14+)
public record User(
Long id,
String username,
String email,
@Deprecated String fullName,
LocalDateTime createdAt,
boolean active
) implements Entity {
public User {
Objects.requireNonNull(username, "Username cannot be null");
Objects.requireNonNull(email, "Email cannot be null");
Objects.requireNonNull(createdAt, "Created date cannot be null");
}
public static User of(String username, String email) {
return new User(null, username, email, null, LocalDateTime.now(), true);
}
public User withId(Long id) {
return new User(id, username, email, fullName, createdAt, active);
}
}
// Exception classes
public class ValidationException extends RuntimeException {
private final List<String> errors;
public ValidationException(String message) {
super(message);
this.errors = List.of(message);
}
public ValidationException(List<String> errors) {
super(String.join(", ", errors));
this.errors = Collections.unmodifiableList(errors);
}
public List<String> getErrors() { return errors; }
}
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String resource, Long id) {
super(String.format("%s with id %d not found", resource, id));
}
}
// Service implementation
@Service(value = "userService", transactional = true)
public class UserService extends AbstractService<User> {
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
private static final int MAX_RETRY_ATTEMPTS = 3;
private static final Duration TIMEOUT = Duration.ofSeconds(30);
private final EmailService emailService;
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
@Inject
public UserService(EmailService emailService,
UserRepository userRepository,
PasswordEncoder passwordEncoder) {
this.emailService = emailService;
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
@Override
protected void validate(User user) throws ValidationException {
List<String> errors = new ArrayList<>();
if (user.username() == null || user.username().trim().isEmpty()) {
errors.add("Username is required");
} else if (!user.username().matches("^[a-zA-Z0-9_]{3,20}$")) {
errors.add("Username must be 3-20 characters, alphanumeric and underscore only");
}
if (user.email() == null || !user.email().matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
errors.add("Valid email is required");
}
if (!errors.isEmpty()) {
throw new ValidationException(errors);
}
}
@Transactional
public User createUser(CreateUserRequest request) throws ValidationException {
logger.info("Creating new user: {}", request.username());
// Check if user already exists
if (userRepository.findByUsername(request.username()).isPresent()) {
throw new ValidationException("Username already exists");
}
if (userRepository.findByEmail(request.email()).isPresent()) {
throw new ValidationException("Email already exists");
}
// Create new user
User user = User.of(request.username(), request.email())
.withId(generateId());
validate(user);
try {
User savedUser = userRepository.save(user);
cache.put(savedUser.id(), savedUser);
// Send welcome email asynchronously
CompletableFuture.runAsync(() ->
emailService.sendWelcomeEmail(savedUser)
).exceptionally(throwable -> {
logger.error("Failed to send welcome email to user {}", savedUser.id(), throwable);
return null;
});
logger.info("Successfully created user with ID: {}", savedUser.id());
return savedUser;
} catch (DataAccessException e) {
logger.error("Database error while creating user", e);
throw new ServiceException("Failed to create user", e);
}
}
public Optional<User> findByUsername(String username) {
return cache.values().stream()
.filter(user -> user.username().equals(username))
.findFirst();
}
public List<User> findActiveUsers() {
return cache.values().stream()
.filter(User::active)
.sorted(Comparator.comparing(User::createdAt).reversed())
.collect(Collectors.toList());
}
@Retry(maxAttempts = MAX_RETRY_ATTEMPTS, backoff = @Backoff(delay = 1000))
public User updateUser(Long id, UpdateUserRequest request) {
User existingUser = findById(id)
.orElseThrow(() -> new ResourceNotFoundException("User", id));
User updatedUser = new User(
id,
request.username() != null ? request.username() : existingUser.username(),
request.email() != null ? request.email() : existingUser.email(),
existingUser.fullName(),
existingUser.createdAt(),
request.active() != null ? request.active() : existingUser.active()
);
validate(updatedUser);
try {
User savedUser = userRepository.save(updatedUser);
cache.put(id, savedUser);
return savedUser;
} catch (DataAccessException e) {
logger.error("Failed to update user with ID: {}", id, e);
throw new ServiceException("Failed to update user", e);
}
}
@Async
public CompletableFuture<Void> deleteUser(Long id) {
return CompletableFuture.runAsync(() -> {
try {
userRepository.deleteById(id);
cache.remove(id);
logger.info("Successfully deleted user with ID: {}", id);
} catch (DataAccessException e) {
logger.error("Failed to delete user with ID: {}", id, e);
throw new ServiceException("Failed to delete user", e);
}
});
}
private Long generateId() {
return System.currentTimeMillis() + (long)(Math.random() * 1000);
}
}
// Utility class
public final class DateUtils {
private DateUtils() {
// Utility class - prevent instantiation
}
private static final DateTimeFormatter ISO_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
public static String formatIsoDateTime(LocalDateTime dateTime) {
return dateTime.atZone(ZoneId.systemDefault()).format(ISO_FORMATTER);
}
public static LocalDateTime parseIsoDateTime(String isoString) {
return LocalDateTime.parse(isoString, ISO_FORMATTER);
}
public static boolean isWithinLastDays(LocalDateTime dateTime, int days) {
return dateTime.isAfter(LocalDateTime.now().minusDays(days));
}
}
// Builder pattern
public class UserQueryBuilder {
private String username;
private String email;
private Boolean active;
private LocalDateTime createdAfter;
private LocalDateTime createdBefore;
private SortOrder sortOrder = SortOrder.ASC;
private String sortBy = "createdAt";
private int limit = 100;
private int offset = 0;
public UserQueryBuilder withUsername(String username) {
this.username = username;
return this;
}
public UserQueryBuilder withEmail(String email) {
this.email = email;
return this;
}
public UserQueryBuilder activeOnly(boolean active) {
this.active = active;
return this;
}
public UserQueryBuilder createdAfter(LocalDateTime date) {
this.createdAfter = date;
return this;
}
public UserQueryBuilder createdBefore(LocalDateTime date) {
this.createdBefore = date;
return this;
}
public UserQueryBuilder sortBy(String field, SortOrder order) {
this.sortBy = field;
this.sortOrder = order;
return this;
}
public UserQueryBuilder limit(int limit) {
this.limit = Math.max(1, Math.min(limit, 1000));
return this;
}
public UserQueryBuilder offset(int offset) {
this.offset = Math.max(0, offset);
return this;
}
public UserQuery build() {
return new UserQuery(username, email, active, createdAfter, createdBefore,
sortBy, sortOrder, limit, offset);
}
}
// Lambda expressions and streams
public class StreamProcessor {
private static final Map<String, Function<String, Object>> TYPE_CONVERTERS = Map.of(
"string", s -> s,
"int", Integer::parseInt,
"double", Double::parseDouble,
"boolean", Boolean::parseBoolean,
"bigdecimal", BigDecimal::new,
"bigint", BigInteger::new
);
public Map<String, Object> processConfig(Properties properties) {
return properties.entrySet().stream()
.filter(entry -> entry.getKey() instanceof String)
.filter(entry -> entry.getValue() != null)
.collect(Collectors.toMap(
entry -> (String) entry.getKey(),
entry -> convertValue((String) entry.getKey(), (String) entry.getValue())
));
}
private Object convertValue(String key, String value) {
String type = determineType(key, value);
return TYPE_CONVERTERS.getOrDefault(type, Function.identity()).apply(value);
}
private String determineType(String key, String value) {
if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
return "boolean";
} else if (value.matches("-?\\d+")) {
return "int";
} else if (value.matches("-?\\d*\\.\\d+")) {
return "double";
} else if (key.toLowerCase().contains("amount") || key.toLowerCase().contains("price")) {
return "bigdecimal";
}
return "string";
}
public List<String> validateEmails(List<String> emails) {
return emails.stream()
.filter(Objects::nonNull)
.map(String::trim)
.filter(email -> !email.isEmpty())
.filter(email -> email.matches("^[A-Za-z0-9+_.-]+@(.+)$"))
.distinct()
.collect(Collectors.toList());
}
public CompletableFuture<List<User>> processUsersAsync(List<User> users) {
return CompletableFuture.supplyAsync(() ->
users.parallelStream()
.filter(User::active)
.filter(user -> user.createdAt().isAfter(LocalDateTime.now().minusYears(1)))
.sorted(Comparator.comparing(User::username))
.collect(Collectors.toList())
);
}
}
// Main class for testing
public class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
try {
// Initialize application context
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// Get service bean
UserService userService = context.getBean(UserService.class);
// Create test users
List<User> users = Arrays.asList(
User.of("john_doe", "john@example.com"),
User.of("jane_smith", "jane@example.com"),
User.of("bob_wilson", "bob@example.com")
);
// Process users
List<CompletableFuture<User>> futures = users.stream()
.map(user -> {
try {
return CompletableFuture.completedFuture(userService.createUser(
new CreateUserRequest(user.username(), user.email())
));
} catch (ValidationException e) {
logger.error("Failed to create user: {}", user.username(), e);
return CompletableFuture.<User>failedFuture(e);
}
})
.collect(Collectors.toList());
// Wait for all to complete
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.thenRun(() -> {
logger.info("All users created successfully");
System.out.println("Application started successfully!");
})
.exceptionally(throwable -> {
logger.error("Failed to initialize users", throwable);
System.err.println("Application startup failed!");
return null;
});
} catch (Exception e) {
logger.error("Application startup failed", e);
System.exit(1);
}
}
}

669
theme-test.md Normal file
View File

@@ -0,0 +1,669 @@
# TextMate Grammar Token Examples
This file contains examples of every major TextMate token style for theme testing.
## Comments
<!-- HTML comment -->
// Single line comment
/_ Multi-line comment _/
# Shell comment
/_ JSDoc comment with @param and @return _/
## Strings
"Double quoted string"
'Single quoted string'
`Backtick string`
"String with \"escaped\" quotes"
'String with \'escaped\' quotes'
`String with \`escaped\` backticks`
## Template Literals
`Simple template literal`
`Template with ${variable} interpolation`
`Template with ${function.call()} expression`
Multi-line template with ${nested.interpolation}
## Numbers
42
-17
3.14159
-0.001
1e10
-2.5e-8
0xFF
0o755
0b1010
## Keywords
if else elif for while do switch case default
function class extends implements import export
return break continue throw try catch finally
var let const static async await yield
new this super null undefined true false
## Storage Types
int float double string boolean char void
static final abstract private public protected
readonly volatile transient synchronized
## Constants
MAX_VALUE
DEFAULT_TIMEOUT
API_ENDPOINT
PI
E
## Variables
variableName
\_privateVariable
$specialVariable
camelCase
snake_case
PascalCase
kebab-case
## Functions
functionName()
method.call()
object.property()
array[index]
arrowFunction => expression
## Operators
- - - / % ++ --
== === != !== > < >= <=
&& || ! & | ^ ~ << >> >>>
= += -= \*= /= %= &= |= ^= <<= >>= >>>=
## Punctuation
, ; : . ... ( ) [ ] { } < > / \\
# @ $ % ^ & \* - \_ + = | ~ ` ?
## Entities
ClassName
InterfaceName
EnumName
TypeName
MethodName
PropertyName
## Tags
<div>
<span>
<p>
<a href="link">
<img src="image.jpg" alt="description" />
## Attributes
class="container"
id="main"
data-value="123"
disabled
required
readonly
## CSS Selectors & Properties
.container
#header
.button:hover
input[type="text"]
::before
::after
color: #ffffff;
background: linear-gradient(45deg, #ff0000, #00ff00);
font-size: 16px;
margin: 0 auto;
padding: 10px 20px;
## Regular Expressions
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
/\d{3}-\d{3}-\d{4}/g
/(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})/
## URLs & Paths
https://example.com/path/to/resource
file:///Users/username/project
./relative/path
../parent/directory
/home/user/documents
## JSON
{
"name": "example",
"version": "1.0.0",
"dependencies": {
"react": "^18.0.0",
"typescript": "^4.9.0"
},
"scripts": {
"start": "node index.js",
"test": "jest"
}
}
## XML/HTML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div class="content">
<h1>Title</h1>
<p>Paragraph text</p>
</div>
</body>
</html>
## SQL
SELECT u.id, u.name, u.email, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.active = true
AND o.created_at >= '2023-01-01'
GROUP BY u.id, u.name, u.email
HAVING COUNT(o.id) > 5
ORDER BY order_count DESC
LIMIT 10;
## GraphQL
query GetUserProfile($userId: ID!, $includePosts: Boolean!) {
user(id: $userId) {
id
name
email
avatar
createdAt
posts @include(if: $includePosts) {
id
title
content
publishedAt
comments(first: 10) {
edges {
node {
id
author
content
createdAt
}
}
}
}
}
}
## Shell/Bash
#!/bin/bash
# Variables
PROJECT*DIR="/home/user/projects"
BACKUP_DIR="$PROJECT_DIR/backups"
TIMESTAMP=$(date +"%Y%m%d*%H%M%S")
# Functions
create*backup() {
local source_dir=$1
local backup_file="$BACKUP_DIR/backup*$TIMESTAMP.tar.gz"
echo "Creating backup of $source_dir..."
tar -czf "$backup_file" "$source_dir"
echo "Backup created: $backup_file"
}
# Conditional logic
if [ -d "$PROJECT_DIR" ]; then
create_backup "$PROJECT_DIR"
else
echo "Project directory not found: $PROJECT_DIR"
exit 1
fi
## Python
import os
import sys
from typing import List, Dict, Optional
import requests
from dataclasses import dataclass
@dataclass
class User:
id: int
name: str
email: Optional[str] = None
active: bool = True
def __post_init__(self):
if not self.name.strip():
raise ValueError("Name cannot be empty")
class UserService:
def **init**(self, api_url: str):
self.api_url = api_url
self.session = requests.Session()
async def get_user(self, user_id: int) -> Optional[User]:
"""Fetch user data from API."""
try:
response = await self.session.get(f"{self.api_url}/users/{user_id}")
response.raise_for_status()
data = response.json()
return User(**data)
except requests.RequestException as e:
print(f"Error fetching user {user_id}: {e}")
return None
## Rust
use std::collections::HashMap;
use std::fs::File;
use std::io::{self, Read};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
pub id: u64,
pub name: String,
pub email: Option<String>, #[serde(default)]
pub active: bool,
pub created_at: chrono::DateTime<chrono::Utc>,
}
impl User {
pub fn new(id: u64, name: String, email: Option<String>) -> Self {
Self {
id,
name,
email,
active: true,
created_at: chrono::Utc::now(),
}
}
pub fn display_name(&self) -> String {
match &self.email {
Some(email) => format!("{} <{}>", self.name, email),
None => self.name.clone(),
}
}
}
pub struct UserService {
api_url: String,
client: reqwest::Client,
}
impl UserService {
pub fn new(api_url: String) -> Self {
Self {
api_url,
client: reqwest::Client::new(),
}
}
pub async fn get_user(&self, user_id: u64) -> Result<User, Box<dyn std::error::Error>> {
let url = format!("{}/users/{}", self.api_url, user_id);
let response = self.client.get(&url).send().await?;
let user: User = response.json().await?;
Ok(user)
}
}
## Go
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"time"
"github.com/gorilla/mux"
)
type User struct {
ID int64 `json:"id"`
Name string `json:"name"`
Email \*string `json:"email,omitempty"`
Active bool `json:"active"`
CreatedAt time.Time `json:"created_at"`
}
type UserService struct {
re UserRepository
}
func NewUserService(repo UserRepository) \*UserService {
return &UserService{repo: repo}
}
func (s *UserService) GetUser(ctx context.Context, id int64) (*User, error) {
user, err := s.repo.FindByID(ctx, id)
if err != nil {
return nil, fmt.Errorf("failed to get user %d: %w", id, err)
}
return user, nil
}
func (s *UserService) CreateUser(ctx context.Context, req *CreateUserRequest) (\*User, error) {
user := &User{
Name: req.Name,
Email: req.Email,
Active: true,
CreatedAt: time.Now(),
}
if err := s.repo.Create(ctx, user); err != nil {
return nil, fmt.Errorf("failed to create user: %w", err)
}
return user, nil
}
## YAML
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
namespace: production
labels:
app: web-app
version: v1.2.3
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
tier: frontend
spec:
containers: - name: web-app
image: nginx:1.21-alpine
ports: - containerPort: 80
protocol: TCP
env: - name: NODE_ENV
value: "production" - name: API_URL
valueFrom:
secretKeyRef:
name: app-secrets
key: api-url
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
## TOML
[project]
name = "example-app"
version = "1.0.0"
description = "An example application"
authors = ["John Doe <john@example.com>"]
license = "MIT"
readme = "README.md"
homepage = "https://example.com"
repository = "https://github.com/johndoe/example-app"
keywords = ["web", "api", "rust"]
categories = ["web-programming"]
edition = "2021"
[dependencies]
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
reqwest = { version = "0.11", features = ["json"] }
chrono = { version = "0.4", features = ["serde"] }
log = "0.4"
env_logger = "0.10"
[dev-dependencies]
tokio-test = "0.4"
mockito = "1.0"
[[bin]]
name = "server"
path = "src/main.rs"
[[bin]]
name = "client"
path = "src/client.rs"
## Dockerfile
FROM node:18-alpine AS base
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \
fi
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
# ENV NEXT_TELEMETRY_DISABLED 1
RUN \
if [ -f yarn.lock ]; then yarn run build; \
elif [ -f package-lock.json ]; then npm run build; \
elif [ -f pnpm-lock.yaml ]; then pnpm run build; \
else echo "Lockfile not found." && exit 1; \
fi
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
# Set the correct permission for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
# set hostname to localhost
ENV HOSTNAME "0.0.0.0"
# server.js is created by next build from the standalone output
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
CMD ["node", "server.js"]
## Makefile
.PHONY: help build test clean install dev lint format
# Default target
.DEFAULT_GOAL := help
# Variables
APP_NAME := myapp
VERSION := $(shell git describe --tags --always --dirty)
BUILD_DIR := ./build
DIST_DIR := ./dist
GO_FILES := $(shell find . -name '\*.go' -type f)
help: ## Show this help message
@echo "Available targets:"
@grep -E '^[a-zA-Z_-]+:._?## ._$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.\*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
install: ## Install dependencies
go mod download
npm install
build: ## Build the application
@echo "Building $(APP_NAME) version $(VERSION)..."
mkdir -p $(BUILD_DIR)
go build -ldflags "-X main.version=$(VERSION)" -o $(BUILD_DIR)/$(APP_NAME) ./cmd/main.go
test: ## Run tests
go test -v ./...
npm test
lint: ## Run linters
golangci-lint run
npx eslint .
format: ## Format code
go fmt ./...
npx prettier --write .
dev: ## Run in development mode
go run ./cmd/main.go --dev
clean: ## Clean build artifacts
rm -rf $(BUILD_DIR)
rm -rf $(DIST_DIR)
go clean -cache
docker-build: ## Build Docker image
docker build -t $(APP_NAME):$(VERSION) .
docker tag $(APP_NAME):$(VERSION) $(APP_NAME):latest
docker-run: ## Run Docker container
docker run -p 8080:8080 $(APP_NAME):latest
release: ## Create a new release
@echo "Creating release $(VERSION)"
git tag -a $(VERSION) -m "Release $(VERSION)"
git push origin $(VERSION)
goreleaser release --rm-dist
## Git Diff
diff --git a/src/components/UserProfile.tsx b/src/components/UserProfile.tsx
index 1234567..abcdefg 100644
--- a/src/components/UserProfile.tsx
+++ b/src/components/UserProfile.tsx
@@ -10,7 +10,7 @@ interface User {
id: number
name: string
email?: string
- createdAt: Date
* readonly createdAt: Date
active: boolean
}
@@ -25,8 +25,12 @@ const UserProfile: FC<{ user: User }> = ({ user }) => {
const [isEditing, setIsEditing] = useState(false)
const [formData, setFormData] = useState(user)
- const handleSubmit = async (e: React.FormEvent) => {
- e.preventDefault()
- // Handle form submission
- }
- return (
* <div className="user-card">
- <div className={`user-card ${user.active ? 'active' : 'inactive'}`}>
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>

View File

@@ -29,6 +29,8 @@ class Repository<T> {
} }
public find(id: number): T | undefined { public find(id: number): T | undefined {
const x = undefined
type x = { foo: undefined }
return this.items.find((item) => item.id === id) return this.items.find((item) => item.id === id)
} }
@@ -66,6 +68,72 @@ const sql = `
AND created_at > '${new Date().toISOString()}' AND created_at > '${new Date().toISOString()}'
` `
// String source examples (CSS-in-JS, GraphQL, etc.)
const styledComponent = css`
.container {
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 2rem;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
&:hover {
transform: translateY(-2px);
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.15);
}
.title {
font-size: 1.5rem;
font-weight: bold;
color: white;
margin-bottom: 1rem;
}
}
`
const graphqlQuery = `
query GetUserProfile($userId: ID!) {
user(id: $userId) {
id
name
email
avatar
createdAt
posts {
id
title
content
publishedAt
comments {
id
author
content
createdAt
}
}
}
}
`
const htmlTemplate = `
<div class="user-card">
<img src="${user.avatar}" alt="${user.name}" class="avatar" />
<div class="user-info">
<h3>${user.name}</h3>
<p>${user.email}</p>
<span class="status ${user.active ? "active" : "inactive"}">
${user.active ? "Active" : "Inactive"}
</span>
</div>
<div class="actions">
<button onclick="editUser(${user.id})">Edit</button>
<button onclick="deleteUser(${user.id})" class="danger">Delete</button>
</div>
</div>
`
// Arrow functions // Arrow functions
const debounce = <T extends (...args: any[]) => any>( const debounce = <T extends (...args: any[]) => any>(
func: T, func: T,