feat: implement English Style Converter

- SvelteKit project scaffolded with TypeScript
- Type definitions for Style, StyleCategory, ConversionRequest, ConversionResponse, LLMConfig
- Style definitions with 6 categories and 25 sub-styles
- Intensity mapping (1-5) with prompt modifier placeholders
- LLM client using OpenAI-compatible API (Ollama default)
- POST /api/convert endpoint with input validation
- Animated loading modal with per-letter animations
- Main page UI with category/style selectors, intensity slider
- Copy to clipboard, collapsible prompt display
- Vitest tests for styles, LLM prompt building, and API validation
- Environment configuration for LLM settings
This commit is contained in:
2026-04-12 21:53:27 -04:00
parent fcf80638e1
commit a12afb792e
16 changed files with 1464 additions and 37 deletions

34
src/lib/llm.test.ts Normal file
View File

@@ -0,0 +1,34 @@
import { describe, it, expect } from 'vitest';
import { buildSystemPrompt, buildUserMessage } from '$lib/llm';
describe('buildSystemPrompt', () => {
it('fills in {style} placeholder from intensity instruction', () => {
const result = buildSystemPrompt(
'Rewrite in a sarcastic, snarky tone with biting wit',
'rewrite strongly in a {style} style'
);
expect(result).toContain('rewrite strongly in a Rewrite in a sarcastic, snarky tone with biting wit style');
expect(result).not.toContain('{style}');
});
it('includes the style modifier on its own line', () => {
const result = buildSystemPrompt('some modifier', 'lightly hint at a {style} tone');
expect(result).toContain('some modifier');
});
it('includes the core instruction text', () => {
const result = buildSystemPrompt('test', 'rewrite with a {style} tone');
expect(result).toContain('You are an expert English style converter');
expect(result).toContain('Output ONLY the converted text');
});
});
describe('buildUserMessage', () => {
it('returns the text as-is', () => {
expect(buildUserMessage('Hello world')).toBe('Hello world');
});
it('preserves whitespace', () => {
expect(buildUserMessage(' spaced ')).toBe(' spaced ');
});
});