diff --git a/components/blocks/autofunction.js b/components/blocks/autofunction.js index 05062a554..a3e1702db 100644 --- a/components/blocks/autofunction.js +++ b/components/blocks/autofunction.js @@ -85,16 +85,32 @@ const Autofunction = ({ ); pres.forEach((ele) => { + // Detect language based on pre element class + const isLiteralBlock = ele.classList.contains("literal-block"); + const language = isLiteralBlock ? "bash" : "python"; + const displayLanguage = isLiteralBlock ? "BASH" : "PYTHON"; + const codeText = ele.innerHTML; const preTag = ele.cloneNode(true); const codeWrap = document.createElement("div"); codeWrap.setAttribute("class", styles.CodeBlockContainer); + + // Create language header + const header = document.createElement("div"); + header.setAttribute("class", `${styles.Header} code-block-header`); + const langSpan = document.createElement("span"); + langSpan.setAttribute("class", styles.Language); + langSpan.textContent = displayLanguage; + header.appendChild(langSpan); + const codeTag = document.createElement("code"); - codeTag.setAttribute("class", "language-python"); + codeTag.setAttribute("class", `language-${language}`); preTag.classList.add("line-numbers"); codeTag.innerHTML = codeText; preTag.textContent = null; preTag.appendChild(codeTag); + + codeWrap.appendChild(header); codeWrap.appendChild(preTag); ele.replaceWith(codeWrap); }); diff --git a/components/blocks/autofunction.module.css b/components/blocks/autofunction.module.css index fcbec2131..fcc258988 100644 --- a/components/blocks/autofunction.module.css +++ b/components/blocks/autofunction.module.css @@ -2,6 +2,10 @@ @apply mt-6; } +.Container h4 { + @apply mb-4; +} + .HeaderContainer { @apply mb-6; } @@ -58,13 +62,26 @@ @apply mb-7 relative; } +.Header { + @apply flex items-center px-3 py-1 bg-gray-20 text-gray-70 text-xs font-medium tracking-wide rounded-t-xl border-b border-gray-30; + min-height: 2.5rem; +} + +:global(.dark) .Header { + @apply bg-gray-90 text-gray-50 border-gray-80; +} + +.Language { + @apply uppercase tracking-wider pr-4; +} + .CodeBlockContainer pre, .CodeBlockContainer code { @apply overflow-auto max-w-full whitespace-pre; } .CodeBlockContainer pre { - @apply p-4 bg-gray-10 text-gray-80 font-medium rounded-xl relative leading-relaxed; + @apply p-6 bg-gray-10 text-gray-80 font-medium rounded-b-xl relative leading-relaxed; } .CodeBlockContainer pre code { @@ -76,16 +93,16 @@ } .CodeBlockContainer button { - @apply absolute top-2 right-2 cursor-pointer h-8 w-8 mb-0 flex items-center; + @apply absolute top-2 right-1 cursor-pointer h-8 w-8 mb-0 flex items-center justify-center; } .CodeBlockContainer button::before { - @apply absolute top-2 right-2 z-10 transition-all duration-75 hover:opacity-40; + @apply z-10 transition-all duration-75 hover:opacity-40; content: url("/clipboard.svg"); } .CodeBlockContainer button span { - @apply absolute right-10 text-gray-80 font-mono text-sm tracking-tight font-normal opacity-0; + @apply absolute -top-0.5 right-10 text-gray-80 font-mono text-sm tracking-tight font-normal opacity-0; } .CodeBlockContainer button:hover span { diff --git a/components/blocks/code.js b/components/blocks/code.js index db5595074..b02f5ef2d 100644 --- a/components/blocks/code.js +++ b/components/blocks/code.js @@ -15,6 +15,44 @@ import styles from "./code.module.css"; // Initialize the cache for imported languages. const languageImports = new Map(); +// Map language identifiers to display-friendly names +const languageDisplayNames = { + python: "Python", + javascript: "JavaScript", + js: "JavaScript", + typescript: "TypeScript", + ts: "TypeScript", + bash: "Bash", + sh: "Bash", + shell: "Shell", + json: "JSON", + yaml: "YAML", + yml: "YAML", + html: "HTML", + css: "CSS", + sql: "SQL", + toml: "TOML", + markdown: "Markdown", + md: "Markdown", + jsx: "JSX", + tsx: "TSX", + go: "Go", + rust: "Rust", + ruby: "Ruby", + java: "Java", + c: "C", + cpp: "C++", + csharp: "C#", + php: "PHP", + swift: "Swift", + kotlin: "Kotlin", + scala: "Scala", + r: "R", + docker: "Docker", + dockerfile: "Dockerfile", + none: "", +}; + const Code = ({ code, children, @@ -29,7 +67,7 @@ const Code = ({ useEffect(() => { // Get the language from the className, if it exists. // Classname usually is `language-python`, `language-javascript`, `language-bash`, etc. - let importLanguage = children.props.className?.substring(9); + let importLanguage = children?.props?.className?.substring(9); // If no language, default to Phython if (importLanguage === undefined || importLanguage === "undefined") { @@ -83,6 +121,19 @@ const Code = ({ languageClass = children.props.className; } + // Extract language identifier for display + const langId = languageClass?.substring(9) || language || "python"; + const displayLanguage = languageDisplayNames[langId] || langId; + const showLanguage = langId.toLowerCase() !== "none"; + + const Header = ( +
+ {showLanguage && ( + {displayLanguage} + )} +
+ ); + if (img) { ConditionalRendering = (
+ {Header} -
+        
           
             {customCode}
           
@@ -105,7 +157,8 @@ const Code = ({
           [styles.NoCopyButton]: hideCopyButton,
         })}
       >
-        
+        {Header}
+        
           
             {customCode}
           
@@ -119,7 +172,8 @@ const Code = ({
           [styles.NoCopyButton]: hideCopyButton,
         })}
       >
-        
+        {Header}
+        
           
             {customCode}
           
diff --git a/components/blocks/code.module.css b/components/blocks/code.module.css
index 213188c9b..ee9119bce 100644
--- a/components/blocks/code.module.css
+++ b/components/blocks/code.module.css
@@ -3,6 +3,23 @@
   @apply relative !important;
 }
 
+.Header {
+  @apply flex items-center px-3 py-1 bg-gray-20 text-gray-70 text-xs font-medium tracking-wide rounded-t-md border-b border-gray-30;
+  min-height: 2.5rem;
+}
+
+:global(.dark) .Header {
+  @apply bg-gray-90 text-gray-50 border-gray-80;
+}
+
+.Language {
+  @apply uppercase tracking-wider pr-4;
+}
+
+.HasHeader {
+  @apply rounded-t-none !important;
+}
+
 .Pre,
 .Container code {
   @apply overflow-auto max-w-full whitespace-pre;
@@ -29,16 +46,16 @@
   @apply bg-gray-80 opacity-30 z-0;
 }
 .Container button {
-  @apply absolute top-2 right-2 cursor-pointer h-8 w-8 mb-0 flex items-center;
+  @apply absolute top-2 right-1 cursor-pointer h-8 w-8 mb-0 flex items-center justify-center;
 }
 
 .Container button::before {
-  @apply absolute top-2 right-2 z-10 transition-all duration-75 hover:opacity-40;
+  @apply z-10 transition-all duration-75 hover:opacity-40;
   content: url("/clipboard.svg");
 }
 
 .Container button span {
-  @apply absolute right-10 text-gray-80 font-mono text-sm tracking-tight font-normal opacity-0;
+  @apply absolute -top-0.5 right-10 text-gray-80 font-mono text-sm tracking-tight font-normal opacity-0;
 }
 
 .Container button:hover span {
diff --git a/components/blocks/refCard.module.css b/components/blocks/refCard.module.css
index 70e4987b1..931cb50a4 100644
--- a/components/blocks/refCard.module.css
+++ b/components/blocks/refCard.module.css
@@ -153,6 +153,10 @@
   @apply hidden;
 }
 
+.Container section :global(.code-block-header) {
+  @apply hidden !important;
+}
+
 .Container section div {
   @apply bg-gray-10;
   @apply text-gray-80;