acme / web-platform / src
๐Ÿ””
AK
๐Ÿ“„ Code
๐Ÿ”€ Pull Requests 7
โš  Issues 23
๐Ÿš€ Actions
๐Ÿ“Š Projects
๐Ÿ“‹ Wiki
โš™ Settings
๐Ÿ“œ

codeViewer.ts

TypeScript ยท 2,847 bytes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
/**
* CodeViewer โ€” Renders syntax-highlighted source files
* with line-by-line blame annotations and diff overlays.
*/
import { SyntaxHighlighter } from "@.git/syntax";
import { BlameService } from "@.git/blame";
import { type FileContent, LineBlame, DiffHunk } from "@.git/types";
export interface CodeViewerProps {
filePath: string;
content: FileContent;
blameInfo?: LineBlame[];
diffHunks?: DiffHunk[];
onLineClick?: (line: number) => void;
}
export class CodeViewer {
private highlighter: SyntaxHighlighter;
private blameService: BlameService;
private _props: CodeViewerProps;
private _container: HTMLElement;
// Line 21: constructor
constructor(container: HTMLElement, props: CodeViewerProps) {
this._container = container;
this._props = props;
this.highlighter = new SyntaxHighlighter({
theme: "dark",
languages: ["typescript", "javascript", "css", "html"],
});
this.blameService = new BlameService();
}
// Line 38: Render the code with syntax highlighting
async render(): Promise<void> {
const lines = this._props.content.split("\n");
const lang = this.detectLanguage(this._props.filePath);
// Apply syntax highlighting
const highlighted = await this.highlighter.highlight(lines, lang);
// Fetch blame annotations if available
let blames: LineBlame[] = this._props.blameInfo || [];
if (blames.length === 0) {
blames = await this.blameService.annotate(this._props.filePath);
}
// Render to DOM
this._renderLines(highlighted, blames);
this._bindEvents();
}
// Line 57: Build DOM nodes for each line
private _renderLines(
lines: string[],
blames: LineBlame[]
): void {
const fragment = document.createDocumentFragment();
lines.forEach((html, index) => {
const blame = blames[index] || null;
const lineEl = document.createElement("div");
lineEl.className = "code-line" + (blame ? ` blame:${blame.hash}` : "");
lineEl.innerHTML = `<span class="line-num">${index + 1}</span> ${html}`;
fragment.appendChild(lineEl);
});
this._container.innerHTML = "";
this._container.appendChild(fragment);
}
// Line 75: Attach click handlers for blame tooltips
private _bindEvents(): void {
this._container.addEventListener("click", (e) => {
const target = (e.target as HTMLElement).closest(".code-line");
if (target) this._props.onLineClick?.call(undefined, Number(target.dataset.line));
});
}
// Detect file language from extension
private detectLanguage(path: string): string {
return path.split(".").pop() || "text";
}
}
Blame
Commits
Branches
JL
julia_lin
2 hours ago
refactor(ui): add blame annotations to code viewer with tooltip support
a8f3c12
Commit History
โ—‰
add blame annotations to code viewer
julia_lin a8f3c12 2h ago
โ—‰
feat: implement multi-language syntax highlighting
alex.kim b7e2d09 5h ago
โŠ•
Merge pull request #342 from feature/diff-view
alex.kim c4a1e88 1d ago
โ—‰
fix: handle empty blame responses gracefully
marcus_r d2f0c55 2d ago
โ—‰
feat: add diff view with inline hunks
marcus_r e1b9a44 3d ago
โ—‰
chore: update type definitions for FileContent
julia_lin f0c8d33 4d ago
โŠ•
Merge branch 'main' into feature/code-viewer
alex.kim a5d7b22 5d ago
โ—‰ main*
โŠ— 3 unstaged
โŠ• 1 staged
Ln 38, Col 24
Spaces: 2
UTF-8
TypeScript
Prettier โœ“
ESLint