feat: add CodeMirror syntax highlighting to section page code blocks
- Use CodeMirror in read-only mode for code examples - Auto-detect CSS vs HTML based on content - Clean up views when navigating between sections - Add transparent background to blend with code-block container 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
72
src/app.js
72
src/app.js
@@ -6,6 +6,13 @@ import { initI18n, t, getLanguage, setLanguage, applyTranslations } from "./i18n
|
||||
import { parseHash, updateHash, replaceHash, getShareableUrl, RouteType, navigateTo } from "./helpers/router.js";
|
||||
import { sections, getSection, getModuleSection, getModulesBySection } from "./config/sections.js";
|
||||
|
||||
// CodeMirror imports for syntax highlighting
|
||||
import { EditorState } from "@codemirror/state";
|
||||
import { EditorView } from "@codemirror/view";
|
||||
import { oneDark } from "@codemirror/theme-one-dark";
|
||||
import { html } from "@codemirror/lang-html";
|
||||
import { css } from "@codemirror/lang-css";
|
||||
|
||||
// Simplified state - LessonEngine now manages lesson state and progress
|
||||
const state = {
|
||||
userSettings: {
|
||||
@@ -16,6 +23,69 @@ const state = {
|
||||
animationTimeout: null
|
||||
};
|
||||
|
||||
// Track CodeMirror views for cleanup
|
||||
let sectionCodeViews = [];
|
||||
|
||||
// Read-only CodeMirror theme for code examples
|
||||
const readOnlyTheme = EditorView.theme(
|
||||
{
|
||||
"&": {
|
||||
fontSize: "13px"
|
||||
},
|
||||
".cm-content": {
|
||||
fontFamily: "'JetBrains Mono', 'Fira Code', monospace",
|
||||
padding: "12px 0"
|
||||
},
|
||||
".cm-line": {
|
||||
padding: "0 12px"
|
||||
},
|
||||
".cm-gutters": {
|
||||
display: "none"
|
||||
}
|
||||
},
|
||||
{ dark: true }
|
||||
);
|
||||
|
||||
/**
|
||||
* Highlight all code blocks in the section page using CodeMirror
|
||||
*/
|
||||
function highlightSectionCodeBlocks() {
|
||||
// Clean up previous views
|
||||
sectionCodeViews.forEach((view) => view.destroy());
|
||||
sectionCodeViews = [];
|
||||
|
||||
// Find all code blocks in section page
|
||||
const codeBlocks = elements.sectionIntro?.querySelectorAll(".code-block") || [];
|
||||
|
||||
codeBlocks.forEach((block) => {
|
||||
const pre = block.querySelector("pre");
|
||||
const code = block.querySelector("code");
|
||||
if (!pre || !code) return;
|
||||
|
||||
const content = code.textContent || "";
|
||||
|
||||
// Detect language from content
|
||||
const isHTML = content.includes("<") && content.includes(">");
|
||||
const langExtension = isHTML ? html() : css();
|
||||
|
||||
// Create read-only CodeMirror view
|
||||
const state = EditorState.create({
|
||||
doc: content,
|
||||
extensions: [langExtension, oneDark, readOnlyTheme, EditorState.readOnly.of(true), EditorView.lineWrapping]
|
||||
});
|
||||
|
||||
const view = new EditorView({
|
||||
state,
|
||||
parent: block
|
||||
});
|
||||
|
||||
// Remove original pre/code
|
||||
pre.remove();
|
||||
|
||||
sectionCodeViews.push(view);
|
||||
});
|
||||
}
|
||||
|
||||
// DOM elements - updated for new layout
|
||||
const elements = {
|
||||
// Header
|
||||
@@ -1272,6 +1342,8 @@ function showSectionPage(sectionId) {
|
||||
// Inject educational content (includes integrated module links)
|
||||
if (elements.sectionIntro && sectionContent[sectionId]) {
|
||||
elements.sectionIntro.innerHTML = sectionContent[sectionId];
|
||||
// Highlight code blocks with CodeMirror
|
||||
highlightSectionCodeBlocks();
|
||||
}
|
||||
|
||||
// Get modules for this section to calculate progress
|
||||
|
||||
10
src/main.css
10
src/main.css
@@ -1911,6 +1911,7 @@ input:checked + .toggle-slider::before {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Fallback styles for pre/code (before CodeMirror initializes) */
|
||||
.code-block pre {
|
||||
margin: 0;
|
||||
padding: 1rem;
|
||||
@@ -1925,6 +1926,15 @@ input:checked + .toggle-slider::before {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
/* CodeMirror styles within code blocks */
|
||||
.code-block .cm-editor {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.code-block .cm-scroller {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.code-caption {
|
||||
font-size: 0.75rem;
|
||||
color: var(--light-text);
|
||||
|
||||
Reference in New Issue
Block a user