+server.ts
1import { json } from '@sveltejs/kit';
2import { getRepoDir } from '$lib/server/vcs';
3import { highlightLines } from '$lib/server/highlighter';
4import { readFile } from 'fs/promises';
5import { join } from 'path';
6import type { RequestHandler } from './$types.ts';
7
8function getLanguage(filePath: string): string {
9 const ext = filePath.split('.').pop()?.toLowerCase() || '';
10 // Simplified — the full map is in git.ts but we just need the extension here
11 const map: Record<string, string> = {
12 ts: 'typescript', tsx: 'tsx', js: 'javascript', jsx: 'jsx',
13 py: 'python', rb: 'ruby', go: 'go', rs: 'rust', java: 'java',
14 swift: 'swift', kt: 'kotlin', cs: 'csharp', php: 'php',
15 css: 'css', scss: 'scss', html: 'html', svelte: 'svelte', vue: 'vue',
16 json: 'json', yaml: 'yaml', yml: 'yaml', md: 'markdown',
17 sh: 'bash', sql: 'sql', c: 'c', cpp: 'cpp', h: 'c', hpp: 'cpp',
18 m: 'objective-c', dart: 'dart', lua: 'lua', r: 'r', scala: 'scala',
19 ex: 'elixir', hs: 'haskell', toml: 'toml', xml: 'xml'
20 };
21 return map[ext] || 'text';
22}
23
24export const GET: RequestHandler = async ({ url }) => {
25 try {
26 const filePath = url.searchParams.get('file');
27 const startLine = parseInt(url.searchParams.get('start') || '1', 10);
28 const endLine = parseInt(url.searchParams.get('end') || '20', 10);
29
30 if (!filePath) {
31 return json({ error: 'file parameter required' }, { status: 400 });
32 }
33
34 const fullPath = join(getRepoDir(), filePath);
35 const content = await readFile(fullPath, 'utf-8');
36 const allLines = content.split('\n');
37 const language = getLanguage(filePath);
38
39 // Highlight the full file
40 const highlighted = await highlightLines(content, language);
41
42 // Extract requested range (1-indexed)
43 const start = Math.max(1, startLine);
44 const end = Math.min(allLines.length, endLine);
45 const lines = [];
46
47 for (let i = start; i <= end; i++) {
48 lines.push({
49 type: 'context' as const,
50 content: allLines[i - 1],
51 html: highlighted.get(i),
52 oldNumber: i,
53 newNumber: i
54 });
55 }
56
57 return json({ lines, totalLines: allLines.length });
58 } catch (err) {
59 return json({ error: String(err) }, { status: 500 });
60 }
61};