Chapter 7: Syntax Highlighting
← Previous: Quick Actions System
Have you ever read a book where all the text was the same color and size? It can be hard to understand what's important. Now, imagine if important phrases were highlighted in red, character names were in blue, and scene settings were in green. That would be much easier to read, right?
This is exactly what Syntax Highlighting does for our code in the Local Gist Manager application!
The Problem: Plain Text is Hard to Read
Let's say you're looking at this JavaScript code without any highlighting:
function calculateTotal(items) {
let total = 0;
for (const item of items) {
total += item.price * (1 - item.discount);
}
return total;
}
It's not terrible, but everything blends together. Now compare it to the same code with syntax highlighting:
Much better! The keywords, variables, and strings are all different colors, making it easier to understand the code structure at a glance.
What is Syntax Highlighting?
Syntax highlighting is like a smart coloring system for your code. It:
- Identifies different parts of your code (keywords, variables, strings, etc.)
- Applies specific colors to each part
- Makes your code more readable and easier to understand
In our Local Gist Manager, this is crucial because we're all about viewing and editing code snippets!
Meet the SyntaxHighlighter Component
The heart of our syntax highlighting system is the CodeSyntaxHighlighter
component:
import { Prism as PrismSyntaxHighlighter } from "react-syntax-highlighter";
import { oneLight } from "react-syntax-highlighter/dist/esm/styles/prism";
This code imports two critical tools:
1. PrismSyntaxHighlighter
: A library that handles all the hard work of syntax highlighting
2. oneLight
: A light color theme for our highlighted code
Using the Syntax Highlighter
Using our syntax highlighting component is super easy:
<CodeSyntaxHighlighter
content="const greeting = 'Hello, world!';"
language="javascript"
/>
Just provide:
1. The content
you want to highlight (your code)
2. The language
of that code (like "javascript", "python", etc.)
And the component automatically displays beautifully highlighted code!
How Our Component Detects Languages
Sometimes we don't know what programming language a file contains. Our component is smart enough to figure it out based on the filename:
const getLanguage = (lang?: string, filename?: string) => {
if (!lang && filename) {
if (filename.endsWith('.ts')) return 'typescript';
if (filename.endsWith('.js')) return 'javascript';
if (filename.endsWith('.py')) return 'python';
// More language mappings...
}
// Default fallback
return lang || 'markdown';
};
This function: 1. Checks if we already know the language 2. If not, it looks at the file extension (.js, .py, etc.) 3. Returns the appropriate language identifier 4. Falls back to 'markdown' if it can't determine the language
Let's See How It Works Behind the Scenes
When you use the syntax highlighter to display a code snippet in our app, here's what happens step by step:
Let's break down this process:
- Your gist content is passed to the
CodeSyntaxHighlighter
component - The component passes this code to the Prism library along with the language
- Prism breaks your code into "tokens" (keywords, strings, variables, etc.)
- Each token gets assigned a color based on the selected theme
- The highlighted code is rendered to the screen
Making the Highlighting Look Nice
We want our syntax highlighting to look consistent with our application's design. Here's how we customize the appearance:
const customStyle = {
...oneLight,
'pre[class*="language-"]': {
...oneLight['pre[class*="language-"]'],
background: "#fafafa",
margin: 0,
padding: "1rem",
fontSize: "0.875rem",
},
// More styling...
};
This code:
1. Starts with the base oneLight
theme
2. Overrides specific styles to match our application's look and feel
3. Controls things like background color, padding, and font size
Seeing It All Together: The Complete Component
Here's a simplified version of our complete CodeSyntaxHighlighter
component:
const CodeSyntaxHighlighter = ({ content, language, filename }) => {
// Determine the language based on filename or provided language
const detectedLanguage = getLanguage(language, filename);
return (
<div className="syntax-highlighter">
<PrismSyntaxHighlighter
language={detectedLanguage}
style={customStyle}
showLineNumbers={content.split("\n").length > 5}
>
{content}
</PrismSyntaxHighlighter>
</div>
);
};
This component: 1. Takes the code content, language, and optional filename 2. Determines the correct language for highlighting 3. Applies our custom styling 4. Shows line numbers if the code is longer than 5 lines 5. Returns the beautifully highlighted code
Interactive Features
Our syntax highlighter isn't just pretty—it's also interactive! We've added features to make editing easier:
<div
onClick={onClick}
className={`relative group ${className || ''}`}
title={onClick ? "Click to edit" : undefined}
>
{/* Highlighting component here */}
</div>
This wrapper allows users to: 1. Click on code to edit it 2. See a helpful tooltip explaining they can click to edit 3. Interact with the code in a natural way
Making It Work with Different File Types
Our application handles many different types of files and programming languages. Here's a small sample of the languages we support:
- JavaScript/TypeScript
- Python
- HTML/CSS
- JSON
- Markdown
- Ruby
- And many more!
This makes Local Gist Manager extremely versatile for developers who work with different technologies.
Handling Special Cases
Sometimes code has special requirements for display. We handle those too:
<PrismSyntaxHighlighter
language={language}
style={customStyle}
showLineNumbers={content.split("\n").length > 5}
wrapLines={true}
// More options...
>
{content}
</PrismSyntaxHighlighter>
These special features include: 1. Smart line number display (only for longer code blocks) 2. Line wrapping for long lines of code 3. Custom font families for better readability
How the Highlighting Integrates with the Rest of the App
The syntax highlighter is used throughout our application, most prominently in the GistItem
component:
// Inside GistItem.tsx
<CodeSyntaxHighlighter
content={file.content || ""}
language={file.language}
onClick={() => handleEditContent(file.filename, file.content || "")}
className="cursor-pointer hover:bg-slate-50"
filename={file.filename}
/>
This integration: 1. Shows the content of each file with appropriate highlighting 2. Makes the code block clickable for editing 3. Adds visual feedback when hovering over the code 4. Uses the filename to help determine the language
Benefits of Syntax Highlighting
Our syntax highlighting provides several key benefits:
- Readability: Code is much easier to understand at a glance
- Error spotting: Syntax errors often stand out visually
- Structure recognition: The structure of code becomes obvious
- Professional appearance: Your gists look polished and professional
- Learning aid: Great for beginners who are learning programming
Real-World Example: Working with Multiple Languages
Let's say you have a gist with three files: 1. A JavaScript file (app.js) 2. A CSS file (style.css) 3. An HTML file (index.html)
Our syntax highlighter will automatically apply the appropriate highlighting to each:
- JavaScript keywords like
const
,function
, andreturn
might be blue - CSS properties might be green, values might be purple
- HTML tags might be red, attributes might be orange
All of this happens automatically without you having to specify anything!
Conclusion
Syntax highlighting is a seemingly small feature that makes a huge difference in how we interact with code. It transforms plain, monotonous text into a colorful, structured representation that's easier to read, understand, and edit.
In the Local Gist Manager, syntax highlighting is essential for providing a great user experience. It helps you quickly understand the code you're looking at and makes your gists look professional and polished.
Now that you understand how we make your code look beautiful, let's move on to learn about our Styling System and how we create a cohesive visual experience throughout the application.