Commit 9442fe1d authored by Administrator's avatar Administrator

Update frontend/src/components/CodeBlock.jsx via Son of Anton

parent 1c05548e
import React, { useState, useCallback } from "react"; import React, { useState, useCallback, useMemo } from "react";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism"; import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
import { Copy, Check, Download, GitCommitVertical, Loader2, Plus, Pencil } from "lucide-react"; import { Copy, Check, Download, GitCommitVertical, Loader2, Plus, Pencil, Eye } from "lucide-react";
import UIPreview, { buildPreviewHTML } from "./UIPreview";
const PREVIEWABLE_LANGS = new Set(["html", "htm", "jsx", "tsx", "vue", "svelte"]);
const PREVIEWABLE_EXTS = /\.(html?|jsx|tsx|vue|svelte)$/i;
export default React.memo(function CodeBlock({ language, filename, code, linkedRepo, onCommit }) { export default React.memo(function CodeBlock({ language, filename, code, linkedRepo, onCommit }) {
const [copied, setCopied] = useState(false); const [copied, setCopied] = useState(false);
const [committing, setCommitting] = useState(false); const [committing, setCommitting] = useState(false);
const [commitDone, setCommitDone] = useState(false); const [commitDone, setCommitDone] = useState(false);
const [showCommitOptions, setShowCommitOptions] = useState(false); const [showCommitOptions, setShowCommitOptions] = useState(false);
const [showPreview, setShowPreview] = useState(false);
const canPreview = useMemo(() => {
if (PREVIEWABLE_LANGS.has(language)) return true;
if (filename && PREVIEWABLE_EXTS.test(filename)) return true;
// Check if code looks like HTML
if (code.trim().match(/^<!DOCTYPE|^<html|^<div|^<section|^<main|^<header|^<template/i)) return true;
return false;
}, [language, filename, code]);
const previewHTML = useMemo(() => {
if (!canPreview) return null;
return buildPreviewHTML([{ language, filename, code }]);
}, [canPreview, language, filename, code]);
const handleCopy = useCallback(() => { const handleCopy = useCallback(() => {
navigator.clipboard.writeText(code); navigator.clipboard.writeText(code);
...@@ -41,6 +59,7 @@ export default React.memo(function CodeBlock({ language, filename, code, linkedR ...@@ -41,6 +59,7 @@ export default React.memo(function CodeBlock({ language, filename, code, linkedR
const lineCount = code.split("\n").length; const lineCount = code.split("\n").length;
return ( return (
<>
<div className="my-3 rounded-xl overflow-hidden border border-anton-border bg-[#1a1b26]"> <div className="my-3 rounded-xl overflow-hidden border border-anton-border bg-[#1a1b26]">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between px-3 py-1.5 bg-anton-surface border-b border-anton-border gap-2"> <div className="flex items-center justify-between px-3 py-1.5 bg-anton-surface border-b border-anton-border gap-2">
...@@ -49,6 +68,16 @@ export default React.memo(function CodeBlock({ language, filename, code, linkedR ...@@ -49,6 +68,16 @@ export default React.memo(function CodeBlock({ language, filename, code, linkedR
{filename && <span className="text-[10px] text-anton-muted truncate">{filename}</span>} {filename && <span className="text-[10px] text-anton-muted truncate">{filename}</span>}
</div> </div>
<div className="flex items-center gap-0.5 shrink-0"> <div className="flex items-center gap-0.5 shrink-0">
{/* Preview button */}
{canPreview && (
<button
onClick={() => setShowPreview(true)}
className="flex items-center gap-1 px-2 py-1 text-[10px] text-blue-400 hover:bg-blue-400/10 rounded transition"
title="Preview in browser"
>
<Eye size={11} /> Preview
</button>
)}
{/* Git commit buttons */} {/* Git commit buttons */}
{showGit && !commitDone && ( {showGit && !commitDone && (
<div className="relative"> <div className="relative">
...@@ -103,5 +132,15 @@ export default React.memo(function CodeBlock({ language, filename, code, linkedR ...@@ -103,5 +132,15 @@ export default React.memo(function CodeBlock({ language, filename, code, linkedR
{code} {code}
</SyntaxHighlighter> </SyntaxHighlighter>
</div> </div>
{/* Preview Modal */}
{showPreview && previewHTML && (
<UIPreview
html={previewHTML}
title={filename || `${language} preview`}
onClose={() => setShowPreview(false)}
/>
)}
</>
); );
}); });
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment