feat: complete section color coding with logo, hints, editor themes, and footers
- Add section-specific CodeMirror syntax highlighting (purple selectors for CSS) - Logo now uses section colors (CSS purple as default, changes per section) - Add section color coding for hints - Add full footer to section and reference pages - Fix nav highlight updates for sidebar and prev/next navigation - Change welcome module mode to CSS for purple theme on first lesson - Rebrand "Code Crispies" to "CODE CRISPIES" across all translations - Fix scroll to top on section page navigation - Change HTML section color to raspberry (#c75b7a)
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
"id": "welcome",
|
"id": "welcome",
|
||||||
"title": "Welcome",
|
"title": "Welcome",
|
||||||
"description": "Get started with Code Crispies",
|
"description": "Get started with Code Crispies",
|
||||||
"mode": "html",
|
"mode": "css",
|
||||||
"difficulty": "beginner",
|
"difficulty": "beginner",
|
||||||
"excludeFromProgress": true,
|
"excludeFromProgress": true,
|
||||||
"lessons": [
|
"lessons": [
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"id": "welcome",
|
"id": "welcome",
|
||||||
"title": "مرحباً",
|
"title": "مرحباً",
|
||||||
"description": "ابدأ مع Code Crispies",
|
"description": "ابدأ مع Code Crispies",
|
||||||
"mode": "html",
|
"mode": "css",
|
||||||
"difficulty": "beginner",
|
"difficulty": "beginner",
|
||||||
"excludeFromProgress": true,
|
"excludeFromProgress": true,
|
||||||
"lessons": [
|
"lessons": [
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"id": "welcome",
|
"id": "welcome",
|
||||||
"title": "Willkommen",
|
"title": "Willkommen",
|
||||||
"description": "Erste Schritte mit Code Crispies",
|
"description": "Erste Schritte mit Code Crispies",
|
||||||
"mode": "html",
|
"mode": "css",
|
||||||
"difficulty": "beginner",
|
"difficulty": "beginner",
|
||||||
"excludeFromProgress": true,
|
"excludeFromProgress": true,
|
||||||
"lessons": [
|
"lessons": [
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"id": "welcome",
|
"id": "welcome",
|
||||||
"title": "Bienvenido",
|
"title": "Bienvenido",
|
||||||
"description": "Comienza con Code Crispies",
|
"description": "Comienza con Code Crispies",
|
||||||
"mode": "html",
|
"mode": "css",
|
||||||
"difficulty": "beginner",
|
"difficulty": "beginner",
|
||||||
"excludeFromProgress": true,
|
"excludeFromProgress": true,
|
||||||
"lessons": [
|
"lessons": [
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"id": "welcome",
|
"id": "welcome",
|
||||||
"title": "Witaj",
|
"title": "Witaj",
|
||||||
"description": "Rozpocznij przygodę z Code Crispies",
|
"description": "Rozpocznij przygodę z Code Crispies",
|
||||||
"mode": "html",
|
"mode": "css",
|
||||||
"difficulty": "beginner",
|
"difficulty": "beginner",
|
||||||
"excludeFromProgress": true,
|
"excludeFromProgress": true,
|
||||||
"lessons": [
|
"lessons": [
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"id": "welcome",
|
"id": "welcome",
|
||||||
"title": "Ласкаво просимо",
|
"title": "Ласкаво просимо",
|
||||||
"description": "Почніть з Code Crispies",
|
"description": "Почніть з Code Crispies",
|
||||||
"mode": "html",
|
"mode": "css",
|
||||||
"difficulty": "beginner",
|
"difficulty": "beginner",
|
||||||
"excludeFromProgress": true,
|
"excludeFromProgress": true,
|
||||||
"lessons": [
|
"lessons": [
|
||||||
|
|||||||
57
src/app.js
57
src/app.js
@@ -156,6 +156,8 @@ const elements = {
|
|||||||
closeSidebar: document.getElementById("close-sidebar"),
|
closeSidebar: document.getElementById("close-sidebar"),
|
||||||
moduleList: document.getElementById("module-list"),
|
moduleList: document.getElementById("module-list"),
|
||||||
footerLessonLinks: document.getElementById("footer-lesson-links"),
|
footerLessonLinks: document.getElementById("footer-lesson-links"),
|
||||||
|
refFooterLessonLinks: document.getElementById("ref-footer-lesson-links"),
|
||||||
|
sectionFooterLessonLinks: document.getElementById("section-footer-lesson-links"),
|
||||||
progressFill: document.getElementById("progress-fill"),
|
progressFill: document.getElementById("progress-fill"),
|
||||||
progressText: document.getElementById("progress-text"),
|
progressText: document.getElementById("progress-text"),
|
||||||
resetBtn: document.getElementById("reset-btn"),
|
resetBtn: document.getElementById("reset-btn"),
|
||||||
@@ -456,6 +458,13 @@ function selectLesson(moduleId, lessonIndex) {
|
|||||||
|
|
||||||
loadCurrentLesson();
|
loadCurrentLesson();
|
||||||
|
|
||||||
|
// Update section color coding (after loadCurrentLesson to ensure content is loaded first)
|
||||||
|
const newState = lessonEngine.getCurrentState();
|
||||||
|
updateSectionColor(getModuleSection(newState.module));
|
||||||
|
|
||||||
|
// Update nav highlight
|
||||||
|
updateNavHighlight({ type: RouteType.LESSON, moduleId, lessonIndex });
|
||||||
|
|
||||||
// Close sidebar after selection on mobile
|
// Close sidebar after selection on mobile
|
||||||
if (window.innerWidth <= 768) {
|
if (window.innerWidth <= 768) {
|
||||||
closeSidebar();
|
closeSidebar();
|
||||||
@@ -694,11 +703,15 @@ function nextLesson() {
|
|||||||
// Update URL
|
// Update URL
|
||||||
updateHash(newState.module.id, newState.lessonIndex);
|
updateHash(newState.module.id, newState.lessonIndex);
|
||||||
|
|
||||||
if (newState.module.id !== prevModuleId) {
|
const moduleChanged = newState.module.id !== prevModuleId;
|
||||||
|
if (moduleChanged) {
|
||||||
updateModuleHighlight(newState.module.id);
|
updateModuleHighlight(newState.module.id);
|
||||||
updateSectionColor(getModuleSection(newState.module));
|
|
||||||
}
|
}
|
||||||
loadCurrentLesson();
|
loadCurrentLesson();
|
||||||
|
if (moduleChanged) {
|
||||||
|
updateSectionColor(getModuleSection(newState.module));
|
||||||
|
updateNavHighlight({ type: RouteType.LESSON, moduleId: newState.module.id, lessonIndex: newState.lessonIndex });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -711,11 +724,15 @@ function prevLesson() {
|
|||||||
// Update URL
|
// Update URL
|
||||||
updateHash(newState.module.id, newState.lessonIndex);
|
updateHash(newState.module.id, newState.lessonIndex);
|
||||||
|
|
||||||
if (newState.module.id !== prevModuleId) {
|
const moduleChanged = newState.module.id !== prevModuleId;
|
||||||
|
if (moduleChanged) {
|
||||||
updateModuleHighlight(newState.module.id);
|
updateModuleHighlight(newState.module.id);
|
||||||
updateSectionColor(getModuleSection(newState.module));
|
|
||||||
}
|
}
|
||||||
loadCurrentLesson();
|
loadCurrentLesson();
|
||||||
|
if (moduleChanged) {
|
||||||
|
updateSectionColor(getModuleSection(newState.module));
|
||||||
|
updateNavHighlight({ type: RouteType.LESSON, moduleId: newState.module.id, lessonIndex: newState.lessonIndex });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1852,7 +1869,7 @@ function stripHtml(html) {
|
|||||||
* Update page meta tags based on current route for SEO
|
* Update page meta tags based on current route for SEO
|
||||||
*/
|
*/
|
||||||
function updatePageMeta(route) {
|
function updatePageMeta(route) {
|
||||||
const defaultTitle = "Code Crispies - Learn HTML & CSS Interactively | Free Coding Practice";
|
const defaultTitle = "CODE CRISPIES - Learn HTML & CSS Interactively | Free Coding Practice";
|
||||||
const defaultDesc =
|
const defaultDesc =
|
||||||
"Master HTML, CSS, and Tailwind through hands-on coding exercises. Free, open-source learning platform with instant feedback. No account required.";
|
"Master HTML, CSS, and Tailwind through hands-on coding exercises. Free, open-source learning platform with instant feedback. No account required.";
|
||||||
|
|
||||||
@@ -1872,7 +1889,7 @@ function updatePageMeta(route) {
|
|||||||
case RouteType.SECTION: {
|
case RouteType.SECTION: {
|
||||||
const sectionNames = { css: "CSS", html: "HTML", tailwind: "Tailwind CSS" };
|
const sectionNames = { css: "CSS", html: "HTML", tailwind: "Tailwind CSS" };
|
||||||
const sectionName = sectionNames[route.sectionId] || route.sectionId;
|
const sectionName = sectionNames[route.sectionId] || route.sectionId;
|
||||||
title = `${sectionName} Lessons - Code Crispies | Learn ${sectionName}`;
|
title = `${sectionName} Lessons - CODE CRISPIES | Learn ${sectionName}`;
|
||||||
description = `Learn ${sectionName} through interactive coding exercises. Hands-on practice with instant feedback.`;
|
description = `Learn ${sectionName} through interactive coding exercises. Hands-on practice with instant feedback.`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1881,7 +1898,7 @@ function updatePageMeta(route) {
|
|||||||
const module = lessonEngine.modules.find((m) => m.id === route.moduleId);
|
const module = lessonEngine.modules.find((m) => m.id === route.moduleId);
|
||||||
const lesson = module?.lessons[route.lessonIndex];
|
const lesson = module?.lessons[route.lessonIndex];
|
||||||
if (module && lesson) {
|
if (module && lesson) {
|
||||||
title = `${lesson.title} - ${module.title} | Code Crispies`;
|
title = `${lesson.title} - ${module.title} | CODE CRISPIES`;
|
||||||
const lessonDesc = stripHtml(lesson.description || lesson.task);
|
const lessonDesc = stripHtml(lesson.description || lesson.task);
|
||||||
description = lessonDesc.length > 155 ? lessonDesc.slice(0, 152) + "..." : lessonDesc || defaultDesc;
|
description = lessonDesc.length > 155 ? lessonDesc.slice(0, 152) + "..." : lessonDesc || defaultDesc;
|
||||||
}
|
}
|
||||||
@@ -1897,7 +1914,7 @@ function updatePageMeta(route) {
|
|||||||
html: "HTML Elements"
|
html: "HTML Elements"
|
||||||
};
|
};
|
||||||
const refName = refNames[route.refId] || "Reference";
|
const refName = refNames[route.refId] || "Reference";
|
||||||
title = `${refName} Reference - Code Crispies`;
|
title = `${refName} Reference - CODE CRISPIES`;
|
||||||
description = `Quick reference guide for ${refName}. Syntax, examples, and common patterns for web development.`;
|
description = `Quick reference guide for ${refName}. Syntax, examples, and common patterns for web development.`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1913,13 +1930,13 @@ function updatePageMeta(route) {
|
|||||||
// Update Open Graph tags
|
// Update Open Graph tags
|
||||||
const ogTitle = document.querySelector('meta[property="og:title"]');
|
const ogTitle = document.querySelector('meta[property="og:title"]');
|
||||||
const ogDesc = document.querySelector('meta[property="og:description"]');
|
const ogDesc = document.querySelector('meta[property="og:description"]');
|
||||||
if (ogTitle) ogTitle.setAttribute("content", title.replace(" | Code Crispies", "").replace(" - Code Crispies", ""));
|
if (ogTitle) ogTitle.setAttribute("content", title.replace(" | CODE CRISPIES", "").replace(" - CODE CRISPIES", ""));
|
||||||
if (ogDesc) ogDesc.setAttribute("content", description);
|
if (ogDesc) ogDesc.setAttribute("content", description);
|
||||||
|
|
||||||
// Update Twitter tags
|
// Update Twitter tags
|
||||||
const twitterTitle = document.querySelector('meta[name="twitter:title"]');
|
const twitterTitle = document.querySelector('meta[name="twitter:title"]');
|
||||||
const twitterDesc = document.querySelector('meta[name="twitter:description"]');
|
const twitterDesc = document.querySelector('meta[name="twitter:description"]');
|
||||||
if (twitterTitle) twitterTitle.setAttribute("content", title.replace(" | Code Crispies", "").replace(" - Code Crispies", ""));
|
if (twitterTitle) twitterTitle.setAttribute("content", title.replace(" | CODE CRISPIES", "").replace(" - CODE CRISPIES", ""));
|
||||||
if (twitterDesc) twitterDesc.setAttribute("content", description);
|
if (twitterDesc) twitterDesc.setAttribute("content", description);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1994,6 +2011,11 @@ function updateSectionColor(sectionId) {
|
|||||||
} else {
|
} else {
|
||||||
document.body.removeAttribute("data-section");
|
document.body.removeAttribute("data-section");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update code editor theme for section
|
||||||
|
if (codeEditor) {
|
||||||
|
codeEditor.setSection(sectionId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2018,8 +2040,6 @@ function showLandingPage() {
|
|||||||
* Render module links in the landing page footer, grouped by section
|
* Render module links in the landing page footer, grouped by section
|
||||||
*/
|
*/
|
||||||
function renderFooterLessonLinks() {
|
function renderFooterLessonLinks() {
|
||||||
if (!elements.footerLessonLinks) return;
|
|
||||||
|
|
||||||
const modules = lessonEngine.modules || [];
|
const modules = lessonEngine.modules || [];
|
||||||
const sectionGroups = { css: [], html: [] };
|
const sectionGroups = { css: [], html: [] };
|
||||||
|
|
||||||
@@ -2042,8 +2062,17 @@ function renderFooterLessonLinks() {
|
|||||||
html += "</div>";
|
html += "</div>";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update all footer lesson links
|
||||||
|
if (elements.footerLessonLinks) {
|
||||||
elements.footerLessonLinks.innerHTML = html;
|
elements.footerLessonLinks.innerHTML = html;
|
||||||
}
|
}
|
||||||
|
if (elements.refFooterLessonLinks) {
|
||||||
|
elements.refFooterLessonLinks.innerHTML = html;
|
||||||
|
}
|
||||||
|
if (elements.sectionFooterLessonLinks) {
|
||||||
|
elements.sectionFooterLessonLinks.innerHTML = html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update progress indicators on landing page
|
* Update progress indicators on landing page
|
||||||
@@ -2077,7 +2106,6 @@ function updateLandingProgress() {
|
|||||||
function showSectionPage(sectionId) {
|
function showSectionPage(sectionId) {
|
||||||
hideAllPages();
|
hideAllPages();
|
||||||
elements.sectionPage?.classList.remove("hidden");
|
elements.sectionPage?.classList.remove("hidden");
|
||||||
window.scrollTo(0, 0);
|
|
||||||
|
|
||||||
// Update section color
|
// Update section color
|
||||||
updateSectionColor(sectionId);
|
updateSectionColor(sectionId);
|
||||||
@@ -2120,6 +2148,9 @@ function showSectionPage(sectionId) {
|
|||||||
const percent = total > 0 ? Math.round((completed / total) * 100) : 0;
|
const percent = total > 0 ? Math.round((completed / total) * 100) : 0;
|
||||||
if (elements.sectionProgressFill) elements.sectionProgressFill.style.width = `${percent}%`;
|
if (elements.sectionProgressFill) elements.sectionProgressFill.style.width = `${percent}%`;
|
||||||
if (elements.sectionProgressText) elements.sectionProgressText.textContent = `${completed} of ${total} lessons complete`;
|
if (elements.sectionProgressText) elements.sectionProgressText.textContent = `${completed} of ${total} lessons complete`;
|
||||||
|
|
||||||
|
// Scroll to top after content is rendered
|
||||||
|
requestAnimationFrame(() => window.scrollTo(0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export const sections = {
|
|||||||
id: "html",
|
id: "html",
|
||||||
title: "HTML",
|
title: "HTML",
|
||||||
description: "Semantic markup and native elements",
|
description: "Semantic markup and native elements",
|
||||||
color: "#d4637b",
|
color: "#c75b7a",
|
||||||
order: 2
|
order: 2
|
||||||
},
|
},
|
||||||
tailwind: {
|
tailwind: {
|
||||||
|
|||||||
86
src/i18n.js
86
src/i18n.js
@@ -1,11 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* Internationalization module for Code Crispies
|
* Internationalization module for CODE CRISPIES
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const translations = {
|
const translations = {
|
||||||
en: {
|
en: {
|
||||||
// Page
|
// Page
|
||||||
pageTitle: "Code Crispies - Learn HTML & CSS Interactively",
|
pageTitle: "CODE CRISPIES - Learn HTML & CSS Interactively",
|
||||||
skipLink: "Skip to main content",
|
skipLink: "Skip to main content",
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
@@ -48,9 +48,9 @@ const translations = {
|
|||||||
|
|
||||||
// Help dialog
|
// Help dialog
|
||||||
helpTitle: "Help",
|
helpTitle: "Help",
|
||||||
aboutTitle: "About Code Crispies",
|
aboutTitle: "About CODE CRISPIES",
|
||||||
aboutText:
|
aboutText:
|
||||||
"Code Crispies is a free, open-source platform for learning web development through hands-on exercises. No account required - just start coding!",
|
"CODE CRISPIES is a free, open-source platform for learning web development through hands-on exercises. No account required - just start coding!",
|
||||||
learningModesTitle: "Learning Modes",
|
learningModesTitle: "Learning Modes",
|
||||||
modeCss: "<strong>CSS</strong> - Write CSS rules to style elements",
|
modeCss: "<strong>CSS</strong> - Write CSS rules to style elements",
|
||||||
modeTailwind: "<strong>Tailwind</strong> - Apply utility classes directly in HTML",
|
modeTailwind: "<strong>Tailwind</strong> - Apply utility classes directly in HTML",
|
||||||
@@ -85,7 +85,7 @@ const translations = {
|
|||||||
|
|
||||||
// Contact
|
// Contact
|
||||||
contactTitle: "Contact & Links",
|
contactTitle: "Contact & Links",
|
||||||
contactText: 'Code Crispies is developed by <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
contactText: 'CODE CRISPIES is developed by <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||||
|
|
||||||
// Reset dialog
|
// Reset dialog
|
||||||
resetDialogTitle: "Reset Progress",
|
resetDialogTitle: "Reset Progress",
|
||||||
@@ -121,7 +121,7 @@ const translations = {
|
|||||||
landingHeroHighlight: "By Writing Real Code",
|
landingHeroHighlight: "By Writing Real Code",
|
||||||
landingHeroSubtitle: "Master HTML, CSS, and Tailwind through hands-on exercises with instant feedback. Free and open source.",
|
landingHeroSubtitle: "Master HTML, CSS, and Tailwind through hands-on exercises with instant feedback. Free and open source.",
|
||||||
landingCtaStart: "Start Learning NOW",
|
landingCtaStart: "Start Learning NOW",
|
||||||
landingWhyTitle: "Why Code Crispies Works",
|
landingWhyTitle: "Why CODE CRISPIES Works",
|
||||||
landingBenefit1Title: "Learn by Doing",
|
landingBenefit1Title: "Learn by Doing",
|
||||||
landingBenefit1Text: "Write real code from lesson one. No videos to watch—just you, an editor, and instant feedback on every keystroke.",
|
landingBenefit1Text: "Write real code from lesson one. No videos to watch—just you, an editor, and instant feedback on every keystroke.",
|
||||||
landingBenefit2Title: "Practice at Your Pace",
|
landingBenefit2Title: "Practice at Your Pace",
|
||||||
@@ -145,17 +145,17 @@ const translations = {
|
|||||||
footerPlayground: "Playground",
|
footerPlayground: "Playground",
|
||||||
footerAbout: "About",
|
footerAbout: "About",
|
||||||
footerSupport: "Support",
|
footerSupport: "Support",
|
||||||
footerSupportText: "Help keep Code Crispies free and open source.",
|
footerSupportText: "Help keep CODE CRISPIES free and open source.",
|
||||||
footerLicense: "Released into the public domain.",
|
footerLicense: "Released into the public domain.",
|
||||||
|
|
||||||
// Help Dialog Support
|
// Help Dialog Support
|
||||||
supportTitle: "Support the Project",
|
supportTitle: "Support the Project",
|
||||||
supportText: "Help keep Code Crispies free and open source."
|
supportText: "Help keep CODE CRISPIES free and open source."
|
||||||
},
|
},
|
||||||
|
|
||||||
de: {
|
de: {
|
||||||
// Page
|
// Page
|
||||||
pageTitle: "Code Crispies - HTML & CSS interaktiv lernen",
|
pageTitle: "CODE CRISPIES - HTML & CSS interaktiv lernen",
|
||||||
skipLink: "Zum Hauptinhalt springen",
|
skipLink: "Zum Hauptinhalt springen",
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
@@ -198,9 +198,9 @@ const translations = {
|
|||||||
|
|
||||||
// Help dialog
|
// Help dialog
|
||||||
helpTitle: "Hilfe",
|
helpTitle: "Hilfe",
|
||||||
aboutTitle: "Über Code Crispies",
|
aboutTitle: "Über CODE CRISPIES",
|
||||||
aboutText:
|
aboutText:
|
||||||
"Code Crispies ist eine kostenlose Open-Source-Plattform zum Erlernen von Webentwicklung durch praktische Übungen. Kein Konto erforderlich - einfach loslegen!",
|
"CODE CRISPIES ist eine kostenlose Open-Source-Plattform zum Erlernen von Webentwicklung durch praktische Übungen. Kein Konto erforderlich - einfach loslegen!",
|
||||||
learningModesTitle: "Lernmodi",
|
learningModesTitle: "Lernmodi",
|
||||||
modeCss: "<strong>CSS</strong> - Schreibe CSS-Regeln zum Stylen von Elementen",
|
modeCss: "<strong>CSS</strong> - Schreibe CSS-Regeln zum Stylen von Elementen",
|
||||||
modeTailwind: "<strong>Tailwind</strong> - Wende Utility-Klassen direkt im HTML an",
|
modeTailwind: "<strong>Tailwind</strong> - Wende Utility-Klassen direkt im HTML an",
|
||||||
@@ -236,7 +236,7 @@ const translations = {
|
|||||||
|
|
||||||
// Contact
|
// Contact
|
||||||
contactTitle: "Kontakt & Links",
|
contactTitle: "Kontakt & Links",
|
||||||
contactText: 'Code Crispies wird von <a href="https://librete.ch" target="_blank">LibreTECH</a> entwickelt',
|
contactText: 'CODE CRISPIES wird von <a href="https://librete.ch" target="_blank">LibreTECH</a> entwickelt',
|
||||||
|
|
||||||
// Reset dialog
|
// Reset dialog
|
||||||
resetDialogTitle: "Fortschritt zurücksetzen",
|
resetDialogTitle: "Fortschritt zurücksetzen",
|
||||||
@@ -272,7 +272,7 @@ const translations = {
|
|||||||
landingHeroHighlight: "Selbstständig lernen",
|
landingHeroHighlight: "Selbstständig lernen",
|
||||||
landingHeroSubtitle: "Meistere HTML, CSS und Tailwind durch praktische Übungen mit sofortigem Feedback. Kostenlos und Open Source.",
|
landingHeroSubtitle: "Meistere HTML, CSS und Tailwind durch praktische Übungen mit sofortigem Feedback. Kostenlos und Open Source.",
|
||||||
landingCtaStart: "Jetzt starten",
|
landingCtaStart: "Jetzt starten",
|
||||||
landingWhyTitle: "Warum Code Crispies funktioniert",
|
landingWhyTitle: "Warum CODE CRISPIES funktioniert",
|
||||||
landingBenefit1Title: "Lernen durch Praxis",
|
landingBenefit1Title: "Lernen durch Praxis",
|
||||||
landingBenefit1Text:
|
landingBenefit1Text:
|
||||||
"Schreibe echten Code ab der ersten Lektion. Keine Videos – nur du, ein Editor und sofortiges Feedback bei jedem Tastendruck.",
|
"Schreibe echten Code ab der ersten Lektion. Keine Videos – nur du, ein Editor und sofortiges Feedback bei jedem Tastendruck.",
|
||||||
@@ -298,18 +298,18 @@ const translations = {
|
|||||||
footerPlayground: "Playground",
|
footerPlayground: "Playground",
|
||||||
footerAbout: "Über uns",
|
footerAbout: "Über uns",
|
||||||
footerSupport: "Unterstützen",
|
footerSupport: "Unterstützen",
|
||||||
footerSupportText: "Hilf mit, Code Crispies kostenlos und Open Source zu halten.",
|
footerSupportText: "Hilf mit, CODE CRISPIES kostenlos und Open Source zu halten.",
|
||||||
footerLicense: "Gemeinfrei (Public Domain).",
|
footerLicense: "Gemeinfrei (Public Domain).",
|
||||||
|
|
||||||
// Help Dialog Support
|
// Help Dialog Support
|
||||||
supportTitle: "Projekt unterstützen",
|
supportTitle: "Projekt unterstützen",
|
||||||
supportText: "Hilf mit, Code Crispies kostenlos und Open Source zu halten."
|
supportText: "Hilf mit, CODE CRISPIES kostenlos und Open Source zu halten."
|
||||||
},
|
},
|
||||||
|
|
||||||
// Polish
|
// Polish
|
||||||
pl: {
|
pl: {
|
||||||
// Page
|
// Page
|
||||||
pageTitle: "Code Crispies - Nauka HTML i CSS interaktywnie",
|
pageTitle: "CODE CRISPIES - Nauka HTML i CSS interaktywnie",
|
||||||
skipLink: "Przejdź do głównej treści",
|
skipLink: "Przejdź do głównej treści",
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
@@ -352,9 +352,9 @@ const translations = {
|
|||||||
|
|
||||||
// Help dialog
|
// Help dialog
|
||||||
helpTitle: "Pomoc",
|
helpTitle: "Pomoc",
|
||||||
aboutTitle: "O Code Crispies",
|
aboutTitle: "O CODE CRISPIES",
|
||||||
aboutText:
|
aboutText:
|
||||||
"Code Crispies to darmowa platforma open-source do nauki tworzenia stron internetowych poprzez praktyczne ćwiczenia. Nie wymaga konta - po prostu zacznij kodować!",
|
"CODE CRISPIES to darmowa platforma open-source do nauki tworzenia stron internetowych poprzez praktyczne ćwiczenia. Nie wymaga konta - po prostu zacznij kodować!",
|
||||||
learningModesTitle: "Tryby nauki",
|
learningModesTitle: "Tryby nauki",
|
||||||
modeCss: "<strong>CSS</strong> - Pisz reguły CSS do stylizowania elementów",
|
modeCss: "<strong>CSS</strong> - Pisz reguły CSS do stylizowania elementów",
|
||||||
modeTailwind: "<strong>Tailwind</strong> - Stosuj klasy utility bezpośrednio w HTML",
|
modeTailwind: "<strong>Tailwind</strong> - Stosuj klasy utility bezpośrednio w HTML",
|
||||||
@@ -389,7 +389,7 @@ const translations = {
|
|||||||
|
|
||||||
// Contact
|
// Contact
|
||||||
contactTitle: "Kontakt i linki",
|
contactTitle: "Kontakt i linki",
|
||||||
contactText: 'Code Crispies jest rozwijany przez <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
contactText: 'CODE CRISPIES jest rozwijany przez <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||||
|
|
||||||
// Reset dialog
|
// Reset dialog
|
||||||
resetDialogTitle: "Resetuj postęp",
|
resetDialogTitle: "Resetuj postęp",
|
||||||
@@ -425,7 +425,7 @@ const translations = {
|
|||||||
landingHeroHighlight: "Pisząc prawdziwy kod",
|
landingHeroHighlight: "Pisząc prawdziwy kod",
|
||||||
landingHeroSubtitle: "Opanuj HTML, CSS i Tailwind poprzez praktyczne ćwiczenia z natychmiastową informacją zwrotną. Darmowe i open source.",
|
landingHeroSubtitle: "Opanuj HTML, CSS i Tailwind poprzez praktyczne ćwiczenia z natychmiastową informacją zwrotną. Darmowe i open source.",
|
||||||
landingCtaStart: "Zacznij TERAZ",
|
landingCtaStart: "Zacznij TERAZ",
|
||||||
landingWhyTitle: "Dlaczego Code Crispies działa",
|
landingWhyTitle: "Dlaczego CODE CRISPIES działa",
|
||||||
landingBenefit1Title: "Ucz się przez praktykę",
|
landingBenefit1Title: "Ucz się przez praktykę",
|
||||||
landingBenefit1Text:
|
landingBenefit1Text:
|
||||||
"Pisz prawdziwy kod od pierwszej lekcji. Żadnych filmów – tylko ty, edytor i natychmiastowa informacja zwrotna przy każdym naciśnięciu klawisza.",
|
"Pisz prawdziwy kod od pierwszej lekcji. Żadnych filmów – tylko ty, edytor i natychmiastowa informacja zwrotna przy każdym naciśnięciu klawisza.",
|
||||||
@@ -451,18 +451,18 @@ const translations = {
|
|||||||
footerPlayground: "Plac zabaw",
|
footerPlayground: "Plac zabaw",
|
||||||
footerAbout: "O nas",
|
footerAbout: "O nas",
|
||||||
footerSupport: "Wsparcie",
|
footerSupport: "Wsparcie",
|
||||||
footerSupportText: "Pomóż utrzymać Code Crispies darmowym i open source.",
|
footerSupportText: "Pomóż utrzymać CODE CRISPIES darmowym i open source.",
|
||||||
footerLicense: "Udostępnione jako domena publiczna.",
|
footerLicense: "Udostępnione jako domena publiczna.",
|
||||||
|
|
||||||
// Help Dialog Support
|
// Help Dialog Support
|
||||||
supportTitle: "Wesprzyj projekt",
|
supportTitle: "Wesprzyj projekt",
|
||||||
supportText: "Pomóż utrzymać Code Crispies darmowym i open source."
|
supportText: "Pomóż utrzymać CODE CRISPIES darmowym i open source."
|
||||||
},
|
},
|
||||||
|
|
||||||
// Spanish
|
// Spanish
|
||||||
es: {
|
es: {
|
||||||
// Page
|
// Page
|
||||||
pageTitle: "Code Crispies - Aprende HTML y CSS de forma interactiva",
|
pageTitle: "CODE CRISPIES - Aprende HTML y CSS de forma interactiva",
|
||||||
skipLink: "Saltar al contenido principal",
|
skipLink: "Saltar al contenido principal",
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
@@ -505,9 +505,9 @@ const translations = {
|
|||||||
|
|
||||||
// Help dialog
|
// Help dialog
|
||||||
helpTitle: "Ayuda",
|
helpTitle: "Ayuda",
|
||||||
aboutTitle: "Acerca de Code Crispies",
|
aboutTitle: "Acerca de CODE CRISPIES",
|
||||||
aboutText:
|
aboutText:
|
||||||
"Code Crispies es una plataforma gratuita de código abierto para aprender desarrollo web a través de ejercicios prácticos. No se requiere cuenta, ¡solo empieza a programar!",
|
"CODE CRISPIES es una plataforma gratuita de código abierto para aprender desarrollo web a través de ejercicios prácticos. No se requiere cuenta, ¡solo empieza a programar!",
|
||||||
learningModesTitle: "Modos de aprendizaje",
|
learningModesTitle: "Modos de aprendizaje",
|
||||||
modeCss: "<strong>CSS</strong> - Escribe reglas CSS para estilizar elementos",
|
modeCss: "<strong>CSS</strong> - Escribe reglas CSS para estilizar elementos",
|
||||||
modeTailwind: "<strong>Tailwind</strong> - Aplica clases de utilidad directamente en HTML",
|
modeTailwind: "<strong>Tailwind</strong> - Aplica clases de utilidad directamente en HTML",
|
||||||
@@ -543,7 +543,7 @@ const translations = {
|
|||||||
|
|
||||||
// Contact
|
// Contact
|
||||||
contactTitle: "Contacto y enlaces",
|
contactTitle: "Contacto y enlaces",
|
||||||
contactText: 'Code Crispies es desarrollado por <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
contactText: 'CODE CRISPIES es desarrollado por <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||||
|
|
||||||
// Reset dialog
|
// Reset dialog
|
||||||
resetDialogTitle: "Reiniciar progreso",
|
resetDialogTitle: "Reiniciar progreso",
|
||||||
@@ -580,7 +580,7 @@ const translations = {
|
|||||||
landingHeroSubtitle:
|
landingHeroSubtitle:
|
||||||
"Domina HTML, CSS y Tailwind a través de ejercicios prácticos con retroalimentación instantánea. Gratis y de código abierto.",
|
"Domina HTML, CSS y Tailwind a través de ejercicios prácticos con retroalimentación instantánea. Gratis y de código abierto.",
|
||||||
landingCtaStart: "Empieza AHORA",
|
landingCtaStart: "Empieza AHORA",
|
||||||
landingWhyTitle: "Por qué funciona Code Crispies",
|
landingWhyTitle: "Por qué funciona CODE CRISPIES",
|
||||||
landingBenefit1Title: "Aprende haciendo",
|
landingBenefit1Title: "Aprende haciendo",
|
||||||
landingBenefit1Text:
|
landingBenefit1Text:
|
||||||
"Escribe código real desde la primera lección. Sin videos que ver—solo tú, un editor y retroalimentación instantánea en cada tecla.",
|
"Escribe código real desde la primera lección. Sin videos que ver—solo tú, un editor y retroalimentación instantánea en cada tecla.",
|
||||||
@@ -606,18 +606,18 @@ const translations = {
|
|||||||
footerPlayground: "Zona de pruebas",
|
footerPlayground: "Zona de pruebas",
|
||||||
footerAbout: "Acerca de",
|
footerAbout: "Acerca de",
|
||||||
footerSupport: "Apoyar",
|
footerSupport: "Apoyar",
|
||||||
footerSupportText: "Ayuda a mantener Code Crispies gratis y de código abierto.",
|
footerSupportText: "Ayuda a mantener CODE CRISPIES gratis y de código abierto.",
|
||||||
footerLicense: "Liberado al dominio público.",
|
footerLicense: "Liberado al dominio público.",
|
||||||
|
|
||||||
// Help Dialog Support
|
// Help Dialog Support
|
||||||
supportTitle: "Apoyar el proyecto",
|
supportTitle: "Apoyar el proyecto",
|
||||||
supportText: "Ayuda a mantener Code Crispies gratis y de código abierto."
|
supportText: "Ayuda a mantener CODE CRISPIES gratis y de código abierto."
|
||||||
},
|
},
|
||||||
|
|
||||||
// Arabic
|
// Arabic
|
||||||
ar: {
|
ar: {
|
||||||
// Page
|
// Page
|
||||||
pageTitle: "Code Crispies - تعلم HTML و CSS بشكل تفاعلي",
|
pageTitle: "CODE CRISPIES - تعلم HTML و CSS بشكل تفاعلي",
|
||||||
skipLink: "انتقل إلى المحتوى الرئيسي",
|
skipLink: "انتقل إلى المحتوى الرئيسي",
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
@@ -660,8 +660,8 @@ const translations = {
|
|||||||
|
|
||||||
// Help dialog
|
// Help dialog
|
||||||
helpTitle: "مساعدة",
|
helpTitle: "مساعدة",
|
||||||
aboutTitle: "عن Code Crispies",
|
aboutTitle: "عن CODE CRISPIES",
|
||||||
aboutText: "Code Crispies هي منصة مجانية مفتوحة المصدر لتعلم تطوير الويب من خلال تمارين عملية. لا يلزم حساب - فقط ابدأ البرمجة!",
|
aboutText: "CODE CRISPIES هي منصة مجانية مفتوحة المصدر لتعلم تطوير الويب من خلال تمارين عملية. لا يلزم حساب - فقط ابدأ البرمجة!",
|
||||||
learningModesTitle: "أوضاع التعلم",
|
learningModesTitle: "أوضاع التعلم",
|
||||||
modeCss: "<strong>CSS</strong> - اكتب قواعد CSS لتنسيق العناصر",
|
modeCss: "<strong>CSS</strong> - اكتب قواعد CSS لتنسيق العناصر",
|
||||||
modeTailwind: "<strong>Tailwind</strong> - طبق فئات الأدوات مباشرة في HTML",
|
modeTailwind: "<strong>Tailwind</strong> - طبق فئات الأدوات مباشرة في HTML",
|
||||||
@@ -696,7 +696,7 @@ const translations = {
|
|||||||
|
|
||||||
// Contact
|
// Contact
|
||||||
contactTitle: "التواصل والروابط",
|
contactTitle: "التواصل والروابط",
|
||||||
contactText: 'Code Crispies تم تطويره بواسطة <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
contactText: 'CODE CRISPIES تم تطويره بواسطة <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||||
|
|
||||||
// Reset dialog
|
// Reset dialog
|
||||||
resetDialogTitle: "إعادة تعيين التقدم",
|
resetDialogTitle: "إعادة تعيين التقدم",
|
||||||
@@ -732,7 +732,7 @@ const translations = {
|
|||||||
landingHeroHighlight: "بكتابة كود حقيقي",
|
landingHeroHighlight: "بكتابة كود حقيقي",
|
||||||
landingHeroSubtitle: "أتقن HTML و CSS و Tailwind من خلال تمارين عملية مع ملاحظات فورية. مجاني ومفتوح المصدر.",
|
landingHeroSubtitle: "أتقن HTML و CSS و Tailwind من خلال تمارين عملية مع ملاحظات فورية. مجاني ومفتوح المصدر.",
|
||||||
landingCtaStart: "ابدأ الآن",
|
landingCtaStart: "ابدأ الآن",
|
||||||
landingWhyTitle: "لماذا Code Crispies فعال",
|
landingWhyTitle: "لماذا CODE CRISPIES فعال",
|
||||||
landingBenefit1Title: "تعلم بالممارسة",
|
landingBenefit1Title: "تعلم بالممارسة",
|
||||||
landingBenefit1Text: "اكتب كودًا حقيقيًا من الدرس الأول. لا فيديوهات للمشاهدة—فقط أنت ومحرر وملاحظات فورية مع كل ضغطة مفتاح.",
|
landingBenefit1Text: "اكتب كودًا حقيقيًا من الدرس الأول. لا فيديوهات للمشاهدة—فقط أنت ومحرر وملاحظات فورية مع كل ضغطة مفتاح.",
|
||||||
landingBenefit2Title: "بسرعتك الخاصة",
|
landingBenefit2Title: "بسرعتك الخاصة",
|
||||||
@@ -756,18 +756,18 @@ const translations = {
|
|||||||
footerPlayground: "ساحة التجربة",
|
footerPlayground: "ساحة التجربة",
|
||||||
footerAbout: "حول",
|
footerAbout: "حول",
|
||||||
footerSupport: "الدعم",
|
footerSupport: "الدعم",
|
||||||
footerSupportText: "ساعد في إبقاء Code Crispies مجانيًا ومفتوح المصدر.",
|
footerSupportText: "ساعد في إبقاء CODE CRISPIES مجانيًا ومفتوح المصدر.",
|
||||||
footerLicense: "مُطلق للملكية العامة.",
|
footerLicense: "مُطلق للملكية العامة.",
|
||||||
|
|
||||||
// Help Dialog Support
|
// Help Dialog Support
|
||||||
supportTitle: "ادعم المشروع",
|
supportTitle: "ادعم المشروع",
|
||||||
supportText: "ساعد في إبقاء Code Crispies مجانيًا ومفتوح المصدر."
|
supportText: "ساعد في إبقاء CODE CRISPIES مجانيًا ومفتوح المصدر."
|
||||||
},
|
},
|
||||||
|
|
||||||
// Ukrainian
|
// Ukrainian
|
||||||
uk: {
|
uk: {
|
||||||
// Page
|
// Page
|
||||||
pageTitle: "Code Crispies - Вивчай HTML та CSS інтерактивно",
|
pageTitle: "CODE CRISPIES - Вивчай HTML та CSS інтерактивно",
|
||||||
skipLink: "Перейти до основного вмісту",
|
skipLink: "Перейти до основного вмісту",
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
@@ -810,9 +810,9 @@ const translations = {
|
|||||||
|
|
||||||
// Help dialog
|
// Help dialog
|
||||||
helpTitle: "Допомога",
|
helpTitle: "Допомога",
|
||||||
aboutTitle: "Про Code Crispies",
|
aboutTitle: "Про CODE CRISPIES",
|
||||||
aboutText:
|
aboutText:
|
||||||
"Code Crispies — це безкоштовна платформа з відкритим кодом для вивчення веб-розробки через практичні вправи. Обліковий запис не потрібен — просто починайте кодувати!",
|
"CODE CRISPIES — це безкоштовна платформа з відкритим кодом для вивчення веб-розробки через практичні вправи. Обліковий запис не потрібен — просто починайте кодувати!",
|
||||||
learningModesTitle: "Режими навчання",
|
learningModesTitle: "Режими навчання",
|
||||||
modeCss: "<strong>CSS</strong> - Пишіть правила CSS для стилізації елементів",
|
modeCss: "<strong>CSS</strong> - Пишіть правила CSS для стилізації елементів",
|
||||||
modeTailwind: "<strong>Tailwind</strong> - Застосовуйте утилітарні класи безпосередньо в HTML",
|
modeTailwind: "<strong>Tailwind</strong> - Застосовуйте утилітарні класи безпосередньо в HTML",
|
||||||
@@ -847,7 +847,7 @@ const translations = {
|
|||||||
|
|
||||||
// Contact
|
// Contact
|
||||||
contactTitle: "Контакти та посилання",
|
contactTitle: "Контакти та посилання",
|
||||||
contactText: 'Code Crispies розроблено <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
contactText: 'CODE CRISPIES розроблено <a href="https://librete.ch" target="_blank">LibreTECH</a>',
|
||||||
|
|
||||||
// Reset dialog
|
// Reset dialog
|
||||||
resetDialogTitle: "Скинути прогрес",
|
resetDialogTitle: "Скинути прогрес",
|
||||||
@@ -883,7 +883,7 @@ const translations = {
|
|||||||
landingHeroHighlight: "Пишучи справжній код",
|
landingHeroHighlight: "Пишучи справжній код",
|
||||||
landingHeroSubtitle: "Опануй HTML, CSS та Tailwind через практичні вправи з миттєвим зворотним зв'язком. Безкоштовно та з відкритим кодом.",
|
landingHeroSubtitle: "Опануй HTML, CSS та Tailwind через практичні вправи з миттєвим зворотним зв'язком. Безкоштовно та з відкритим кодом.",
|
||||||
landingCtaStart: "Почни ЗАРАЗ",
|
landingCtaStart: "Почни ЗАРАЗ",
|
||||||
landingWhyTitle: "Чому Code Crispies працює",
|
landingWhyTitle: "Чому CODE CRISPIES працює",
|
||||||
landingBenefit1Title: "Вчись на практиці",
|
landingBenefit1Title: "Вчись на практиці",
|
||||||
landingBenefit1Text:
|
landingBenefit1Text:
|
||||||
"Пиши справжній код з першого уроку. Жодних відео—тільки ти, редактор і миттєвий зворотний зв'язок при кожному натисканні клавіші.",
|
"Пиши справжній код з першого уроку. Жодних відео—тільки ти, редактор і миттєвий зворотний зв'язок при кожному натисканні клавіші.",
|
||||||
@@ -908,12 +908,12 @@ const translations = {
|
|||||||
footerPlayground: "Пісочниця",
|
footerPlayground: "Пісочниця",
|
||||||
footerAbout: "Про нас",
|
footerAbout: "Про нас",
|
||||||
footerSupport: "Підтримка",
|
footerSupport: "Підтримка",
|
||||||
footerSupportText: "Допоможи зберегти Code Crispies безкоштовним та з відкритим кодом.",
|
footerSupportText: "Допоможи зберегти CODE CRISPIES безкоштовним та з відкритим кодом.",
|
||||||
footerLicense: "Передано у суспільне надбання.",
|
footerLicense: "Передано у суспільне надбання.",
|
||||||
|
|
||||||
// Help Dialog Support
|
// Help Dialog Support
|
||||||
supportTitle: "Підтримати проєкт",
|
supportTitle: "Підтримати проєкт",
|
||||||
supportText: "Допоможи зберегти Code Crispies безкоштовним та з відкритим кодом."
|
supportText: "Допоможи зберегти CODE CRISPIES безкоштовним та з відкритим кодом."
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ const crispyTheme = EditorView.theme(
|
|||||||
{ dark: true }
|
{ dark: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
// Syntax highlighting with purple accent
|
// Default syntax highlighting (blue accent)
|
||||||
const crispyHighlight = HighlightStyle.define([
|
const defaultHighlight = HighlightStyle.define([
|
||||||
{ tag: tags.keyword, color: "#c9a6eb" },
|
{ tag: tags.keyword, color: "#c9a6eb" },
|
||||||
{ tag: tags.operator, color: "#cdd6f4" },
|
{ tag: tags.operator, color: "#cdd6f4" },
|
||||||
{ tag: tags.variableName, color: "#89b4fa" },
|
{ tag: tags.variableName, color: "#89b4fa" },
|
||||||
@@ -83,8 +83,42 @@ const crispyHighlight = HighlightStyle.define([
|
|||||||
{ tag: tags.color, color: "#f9e2af" }
|
{ tag: tags.color, color: "#f9e2af" }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Combined theme export
|
// CSS section highlighting (purple selectors)
|
||||||
export const crispyEditorTheme = [crispyTheme, syntaxHighlighting(crispyHighlight)];
|
const cssHighlight = HighlightStyle.define([
|
||||||
|
{ tag: tags.keyword, color: "#c9a6eb" },
|
||||||
|
{ tag: tags.operator, color: "#cdd6f4" },
|
||||||
|
{ tag: tags.variableName, color: "#c9a6eb" },
|
||||||
|
{ tag: tags.propertyName, color: "#89b4fa" },
|
||||||
|
{ tag: tags.attributeName, color: "#89b4fa" },
|
||||||
|
{ tag: tags.className, color: "#c9a6eb" },
|
||||||
|
{ tag: tags.tagName, color: "#c9a6eb" },
|
||||||
|
{ tag: tags.string, color: "#a6e3a1" },
|
||||||
|
{ tag: tags.number, color: "#fab387" },
|
||||||
|
{ tag: tags.bool, color: "#fab387" },
|
||||||
|
{ tag: tags.null, color: "#fab387" },
|
||||||
|
{ tag: tags.comment, color: "#6c7086", fontStyle: "italic" },
|
||||||
|
{ tag: tags.bracket, color: "#cdd6f4" },
|
||||||
|
{ tag: tags.punctuation, color: "#cdd6f4" },
|
||||||
|
{ tag: tags.definition(tags.variableName), color: "#c9a6eb" },
|
||||||
|
{ tag: tags.function(tags.variableName), color: "#89b4fa" },
|
||||||
|
{ tag: tags.atom, color: "#c9a6eb" },
|
||||||
|
{ tag: tags.unit, color: "#a6e3a1" },
|
||||||
|
{ tag: tags.color, color: "#f9e2af" }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Get highlight style based on section
|
||||||
|
function getHighlightForSection(section) {
|
||||||
|
if (section === "css") return cssHighlight;
|
||||||
|
return defaultHighlight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get theme with section-specific highlighting
|
||||||
|
export function getEditorTheme(section) {
|
||||||
|
return [crispyTheme, syntaxHighlighting(getHighlightForSection(section))];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default combined theme export (for backwards compatibility)
|
||||||
|
export const crispyEditorTheme = [crispyTheme, syntaxHighlighting(defaultHighlight)];
|
||||||
|
|
||||||
// Custom overrides for editor styling
|
// Custom overrides for editor styling
|
||||||
const editorTheme = EditorView.theme(
|
const editorTheme = EditorView.theme(
|
||||||
@@ -110,6 +144,7 @@ export class CodeEditor {
|
|||||||
this.options = options;
|
this.options = options;
|
||||||
this.view = null;
|
this.view = null;
|
||||||
this.mode = options.mode || "css";
|
this.mode = options.mode || "css";
|
||||||
|
this.section = options.section || null;
|
||||||
this.onChange = options.onChange || (() => {});
|
this.onChange = options.onChange || (() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +161,7 @@ export class CodeEditor {
|
|||||||
// Build extensions array
|
// Build extensions array
|
||||||
const extensions = [
|
const extensions = [
|
||||||
langExtension,
|
langExtension,
|
||||||
crispyEditorTheme,
|
getEditorTheme(this.section),
|
||||||
editorTheme,
|
editorTheme,
|
||||||
// History for undo/redo
|
// History for undo/redo
|
||||||
history(),
|
history(),
|
||||||
@@ -215,6 +250,17 @@ export class CodeEditor {
|
|||||||
this.init(currentValue);
|
this.init(currentValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set section for theme (css, html, tailwind)
|
||||||
|
*/
|
||||||
|
setSection(section) {
|
||||||
|
if (this.section === section) return;
|
||||||
|
|
||||||
|
this.section = section;
|
||||||
|
const currentValue = this.getValue();
|
||||||
|
this.init(currentValue);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Focus the editor
|
* Focus the editor
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
|
||||||
<!-- Primary Meta Tags -->
|
<!-- Primary Meta Tags -->
|
||||||
<title>Code Crispies - Learn HTML & CSS Interactively | Free Coding Practice</title>
|
<title>CODE CRISPIES - Learn HTML & CSS Interactively | Free Coding Practice</title>
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="Master HTML, CSS, and Tailwind through hands-on coding exercises. Free, open-source learning platform with instant feedback. No account required."
|
content="Master HTML, CSS, and Tailwind through hands-on coding exercises. Free, open-source learning platform with instant feedback. No account required."
|
||||||
@@ -19,14 +19,14 @@
|
|||||||
<!-- Open Graph / Facebook -->
|
<!-- Open Graph / Facebook -->
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="website" />
|
||||||
<meta property="og:url" content="https://codecrispi.es/" />
|
<meta property="og:url" content="https://codecrispi.es/" />
|
||||||
<meta property="og:title" content="Code Crispies - Learn HTML & CSS Interactively" />
|
<meta property="og:title" content="CODE CRISPIES - Learn HTML & CSS Interactively" />
|
||||||
<meta property="og:description" content="Master HTML, CSS, and Tailwind through hands-on coding exercises. Free and open source." />
|
<meta property="og:description" content="Master HTML, CSS, and Tailwind through hands-on coding exercises. Free and open source." />
|
||||||
<meta property="og:image" content="https://codecrispi.es/og-image.png" />
|
<meta property="og:image" content="https://codecrispi.es/og-image.png" />
|
||||||
<meta property="og:site_name" content="Code Crispies" />
|
<meta property="og:site_name" content="CODE CRISPIES" />
|
||||||
|
|
||||||
<!-- Twitter -->
|
<!-- Twitter -->
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
<meta name="twitter:title" content="Code Crispies - Learn HTML & CSS Interactively" />
|
<meta name="twitter:title" content="CODE CRISPIES - Learn HTML & CSS Interactively" />
|
||||||
<meta name="twitter:description" content="Master HTML, CSS, and Tailwind through hands-on coding exercises." />
|
<meta name="twitter:description" content="Master HTML, CSS, and Tailwind through hands-on coding exercises." />
|
||||||
<meta name="twitter:image" content="https://codecrispi.es/og-image.png" />
|
<meta name="twitter:image" content="https://codecrispi.es/og-image.png" />
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
{
|
{
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "WebApplication",
|
"@type": "WebApplication",
|
||||||
"name": "Code Crispies",
|
"name": "CODE CRISPIES",
|
||||||
"description": "Interactive platform for learning HTML, CSS, and Tailwind through hands-on coding exercises",
|
"description": "Interactive platform for learning HTML, CSS, and Tailwind through hands-on coding exercises",
|
||||||
"url": "https://codecrispi.es/",
|
"url": "https://codecrispi.es/",
|
||||||
"applicationCategory": "EducationalApplication",
|
"applicationCategory": "EducationalApplication",
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="why-it-works">
|
<section class="why-it-works">
|
||||||
<h2 data-i18n="landingWhyTitle">Why Code Crispies Works</h2>
|
<h2 data-i18n="landingWhyTitle">Why CODE CRISPIES Works</h2>
|
||||||
<div class="benefits-grid">
|
<div class="benefits-grid">
|
||||||
<article class="benefit-card">
|
<article class="benefit-card">
|
||||||
<svg class="benefit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg class="benefit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
@@ -198,7 +198,7 @@
|
|||||||
</section>
|
</section>
|
||||||
<section class="footer-section footer-support">
|
<section class="footer-section footer-support">
|
||||||
<h4 data-i18n="footerSupport">Support</h4>
|
<h4 data-i18n="footerSupport">Support</h4>
|
||||||
<p data-i18n="footerSupportText">Help keep Code Crispies free and open source.</p>
|
<p data-i18n="footerSupportText">Help keep CODE CRISPIES free and open source.</p>
|
||||||
<script src="https://liberapay.com/libretech/widgets/button.js"></script>
|
<script src="https://liberapay.com/libretech/widgets/button.js"></script>
|
||||||
<noscript><a href="https://liberapay.com/libretech/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
|
<noscript><a href="https://liberapay.com/libretech/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
|
||||||
</section>
|
</section>
|
||||||
@@ -227,6 +227,38 @@
|
|||||||
<!-- Educational content with integrated module links -->
|
<!-- Educational content with integrated module links -->
|
||||||
<div class="section-intro" id="section-intro"></div>
|
<div class="section-intro" id="section-intro"></div>
|
||||||
</article>
|
</article>
|
||||||
|
<footer class="section-footer landing-footer">
|
||||||
|
<div class="footer-grid">
|
||||||
|
<section class="footer-section footer-modules">
|
||||||
|
<div id="section-footer-lesson-links" class="footer-links"></div>
|
||||||
|
</section>
|
||||||
|
<section class="footer-section">
|
||||||
|
<h4 data-i18n="footerResources">Resources</h4>
|
||||||
|
<ul class="footer-links">
|
||||||
|
<li><a href="#reference/css">CSS Reference</a></li>
|
||||||
|
<li><a href="#reference/html">HTML Reference</a></li>
|
||||||
|
<li><a href="#playground/0" data-i18n="footerPlayground">Playground</a></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section class="footer-section">
|
||||||
|
<h4 data-i18n="footerAbout">About</h4>
|
||||||
|
<ul class="footer-links">
|
||||||
|
<li><a href="https://librete.ch" target="_blank">LibreTECH</a></li>
|
||||||
|
<li><a href="https://git.librete.ch/public/code-crispies" target="_blank">Source Code</a></li>
|
||||||
|
<li><a href="https://github.com/nextlevelshit/code-crispies" target="_blank">GitHub</a></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section class="footer-section footer-support">
|
||||||
|
<h4 data-i18n="footerSupport">Support</h4>
|
||||||
|
<p data-i18n="footerSupportText">Help keep CODE CRISPIES free and open source.</p>
|
||||||
|
<script src="https://liberapay.com/libretech/widgets/button.js"></script>
|
||||||
|
<noscript><a href="https://liberapay.com/libretech/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div class="footer-bottom">
|
||||||
|
<p>© 2025 <a href="https://librete.ch">LibreTECH</a>. <span data-i18n="footerLicense">Open source under MIT License.</span></p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Reference/Cheatsheet Pages -->
|
<!-- Reference/Cheatsheet Pages -->
|
||||||
@@ -243,8 +275,37 @@
|
|||||||
<!-- Reference content injected by JS -->
|
<!-- Reference content injected by JS -->
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
<footer class="reference-footer">
|
<footer class="reference-footer landing-footer">
|
||||||
<p>© 2025 <a href="https://librete.ch">LibreTECH</a>. <span data-i18n="footerLicense">Released into public domain.</span></p>
|
<div class="footer-grid">
|
||||||
|
<section class="footer-section footer-modules">
|
||||||
|
<div id="ref-footer-lesson-links" class="footer-links"></div>
|
||||||
|
</section>
|
||||||
|
<section class="footer-section">
|
||||||
|
<h4 data-i18n="footerResources">Resources</h4>
|
||||||
|
<ul class="footer-links">
|
||||||
|
<li><a href="#reference/css">CSS Reference</a></li>
|
||||||
|
<li><a href="#reference/html">HTML Reference</a></li>
|
||||||
|
<li><a href="#playground/0" data-i18n="footerPlayground">Playground</a></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section class="footer-section">
|
||||||
|
<h4 data-i18n="footerAbout">About</h4>
|
||||||
|
<ul class="footer-links">
|
||||||
|
<li><a href="https://librete.ch" target="_blank">LibreTECH</a></li>
|
||||||
|
<li><a href="https://git.librete.ch/public/code-crispies" target="_blank">Source Code</a></li>
|
||||||
|
<li><a href="https://github.com/nextlevelshit/code-crispies" target="_blank">GitHub</a></li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section class="footer-section footer-support">
|
||||||
|
<h4 data-i18n="footerSupport">Support</h4>
|
||||||
|
<p data-i18n="footerSupportText">Help keep CODE CRISPIES free and open source.</p>
|
||||||
|
<script src="https://liberapay.com/libretech/widgets/button.js"></script>
|
||||||
|
<noscript><a href="https://liberapay.com/libretech/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div class="footer-bottom">
|
||||||
|
<p>© 2025 <a href="https://librete.ch">LibreTECH</a>. <span data-i18n="footerLicense">Open source under MIT License.</span></p>
|
||||||
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -389,9 +450,9 @@
|
|||||||
<button id="help-dialog-close" class="dialog-close" aria-label="Close">×</button>
|
<button id="help-dialog-close" class="dialog-close" aria-label="Close">×</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="dialog-content">
|
<div class="dialog-content">
|
||||||
<h4 data-i18n="aboutTitle">About Code Crispies</h4>
|
<h4 data-i18n="aboutTitle">About CODE CRISPIES</h4>
|
||||||
<p data-i18n="aboutText">
|
<p data-i18n="aboutText">
|
||||||
Code Crispies is a free, open-source platform for learning web development through hands-on exercises. No account required -
|
CODE CRISPIES is a free, open-source platform for learning web development through hands-on exercises. No account required -
|
||||||
just start coding!
|
just start coding!
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -455,7 +516,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4 data-i18n="contactTitle">Contact & Links</h4>
|
<h4 data-i18n="contactTitle">Contact & Links</h4>
|
||||||
<p data-i18n-html="contactText">Code Crispies is developed by <a href="https://librete.ch" target="_blank">LibreTECH</a></p>
|
<p data-i18n-html="contactText">CODE CRISPIES is developed by <a href="https://librete.ch" target="_blank">LibreTECH</a></p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://git.librete.ch/public/code-crispies" target="_blank">Gitea</a> – Self-hosted source repository</li>
|
<li><a href="https://git.librete.ch/public/code-crispies" target="_blank">Gitea</a> – Self-hosted source repository</li>
|
||||||
<li><a href="https://github.com/nextlevelshit/code-crispies" target="_blank">GitHub</a> – Public mirror</li>
|
<li><a href="https://github.com/nextlevelshit/code-crispies" target="_blank">GitHub</a> – Public mirror</li>
|
||||||
@@ -463,7 +524,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h4 data-i18n="supportTitle">Support the Project</h4>
|
<h4 data-i18n="supportTitle">Support the Project</h4>
|
||||||
<p data-i18n="supportText">Help keep Code Crispies free and open source.</p>
|
<p data-i18n="supportText">Help keep CODE CRISPIES free and open source.</p>
|
||||||
<div class="help-support" onclick="typeof umami !== 'undefined' && umami.track('support_click', {location: 'help'})">
|
<div class="help-support" onclick="typeof umami !== 'undefined' && umami.track('support_click', {location: 'help'})">
|
||||||
<script src="https://liberapay.com/libretech/widgets/button.js"></script>
|
<script src="https://liberapay.com/libretech/widgets/button.js"></script>
|
||||||
<noscript><a href="https://liberapay.com/libretech/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
|
<noscript><a href="https://liberapay.com/libretech/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
|
||||||
|
|||||||
142
src/main.css
142
src/main.css
@@ -252,11 +252,11 @@ kbd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.logo h1 .code-text {
|
.logo h1 .code-text {
|
||||||
color: var(--primary-color);
|
color: #8b6bc4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo h1 .crispies-text {
|
.logo h1 .crispies-text {
|
||||||
background: var(--primary-color);
|
background: #8b6bc4;
|
||||||
color: white;
|
color: white;
|
||||||
padding: 0.15rem 0.35rem;
|
padding: 0.15rem 0.35rem;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
@@ -264,6 +264,31 @@ kbd {
|
|||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Logo section color coding */
|
||||||
|
[data-section="css"] .logo h1 .code-text {
|
||||||
|
color: #8b6bc4;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-section="css"] .logo h1 .crispies-text {
|
||||||
|
background: #8b6bc4;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-section="html"] .logo h1 .code-text {
|
||||||
|
color: #c75b7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-section="html"] .logo h1 .crispies-text {
|
||||||
|
background: #c75b7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-section="tailwind"] .logo h1 .code-text {
|
||||||
|
color: #26a69a;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-section="tailwind"] .logo h1 .crispies-text {
|
||||||
|
background: #26a69a;
|
||||||
|
}
|
||||||
|
|
||||||
.help-toggle {
|
.help-toggle {
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
@@ -1954,7 +1979,9 @@ input:checked + .toggle-slider::before {
|
|||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer-lesson-links {
|
#footer-lesson-links,
|
||||||
|
#ref-footer-lesson-links,
|
||||||
|
#section-footer-lesson-links {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
}
|
}
|
||||||
@@ -2856,12 +2883,12 @@ input:checked + .toggle-slider::before {
|
|||||||
--section-color-rgb: 139, 107, 196;
|
--section-color-rgb: 139, 107, 196;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HTML Section - Balanced Rose */
|
/* HTML Section - Raspberry */
|
||||||
[data-section="html"] {
|
[data-section="html"] {
|
||||||
--section-color: #d4637b;
|
--section-color: #c75b7a;
|
||||||
--section-color-light: #e08899;
|
--section-color-light: #d97a94;
|
||||||
--section-color-dark: #b84d63;
|
--section-color-dark: #a84862;
|
||||||
--section-color-rgb: 212, 99, 123;
|
--section-color-rgb: 199, 91, 122;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tailwind Section - Balanced Teal */
|
/* Tailwind Section - Balanced Teal */
|
||||||
@@ -2878,7 +2905,7 @@ input:checked + .toggle-slider::before {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nav-link[data-section="html"] {
|
.nav-link[data-section="html"] {
|
||||||
color: #d4637b;
|
color: #c75b7a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link[data-section="tailwind"] {
|
.nav-link[data-section="tailwind"] {
|
||||||
@@ -2893,8 +2920,8 @@ input:checked + .toggle-slider::before {
|
|||||||
|
|
||||||
.nav-link[data-section="html"]:hover,
|
.nav-link[data-section="html"]:hover,
|
||||||
.nav-link[data-section="html"].active {
|
.nav-link[data-section="html"].active {
|
||||||
background: rgba(212, 99, 123, 0.1);
|
background: rgba(199, 91, 122, 0.1);
|
||||||
color: #b84d63;
|
color: #a84862;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link[data-section="tailwind"]:hover,
|
.nav-link[data-section="tailwind"]:hover,
|
||||||
@@ -2903,17 +2930,45 @@ input:checked + .toggle-slider::before {
|
|||||||
color: #00897b;
|
color: #00897b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Logo color coding based on section */
|
/* Hint section colors */
|
||||||
[data-section="css"] .code-text {
|
body[data-section="css"] .hint {
|
||||||
color: #8b6bc4;
|
background: rgba(139, 107, 196, 0.3);
|
||||||
|
border-left-color: #a98cd6;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-section="html"] .code-text {
|
body[data-section="css"] .hint-progress {
|
||||||
color: #d4637b;
|
background: #8b6bc4;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-section="tailwind"] .code-text {
|
body[data-section="html"] .hint {
|
||||||
color: #26a69a;
|
background: rgba(199, 91, 122, 0.3);
|
||||||
|
border-left-color: #d97a94;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-section="html"] .hint-progress {
|
||||||
|
background: #c75b7a;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-section="tailwind"] .hint {
|
||||||
|
background: rgba(38, 166, 154, 0.3);
|
||||||
|
border-left-color: #4db6ac;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[data-section="tailwind"] .hint-progress {
|
||||||
|
background: #26a69a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RTL hint border */
|
||||||
|
[dir="rtl"] body[data-section="css"] .hint {
|
||||||
|
border-right-color: #a98cd6;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] body[data-section="html"] .hint {
|
||||||
|
border-right-color: #d97a94;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] body[data-section="tailwind"] .hint {
|
||||||
|
border-right-color: #4db6ac;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reference nav link colors */
|
/* Reference nav link colors */
|
||||||
@@ -2937,13 +2992,13 @@ input:checked + .toggle-slider::before {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ref-nav-link[data-ref="html"] {
|
.ref-nav-link[data-ref="html"] {
|
||||||
color: #d4637b;
|
color: #c75b7a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ref-nav-link[data-ref="html"]:hover,
|
.ref-nav-link[data-ref="html"]:hover,
|
||||||
.ref-nav-link[data-ref="html"].active {
|
.ref-nav-link[data-ref="html"].active {
|
||||||
background: rgba(212, 99, 123, 0.15);
|
background: rgba(199, 91, 122, 0.15);
|
||||||
color: #b84d63;
|
color: #a84862;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CodeMirror section color overrides */
|
/* CodeMirror section color overrides */
|
||||||
@@ -2966,21 +3021,21 @@ body[data-section="css"] .cm-editor .cm-activeLine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body[data-section="html"] .cm-editor .cm-content {
|
body[data-section="html"] .cm-editor .cm-content {
|
||||||
caret-color: #d4637b !important;
|
caret-color: #c75b7a !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-section="html"] .cm-editor .cm-cursor,
|
body[data-section="html"] .cm-editor .cm-cursor,
|
||||||
body[data-section="html"] .cm-editor .cm-dropCursor {
|
body[data-section="html"] .cm-editor .cm-dropCursor {
|
||||||
border-left-color: #d4637b !important;
|
border-left-color: #c75b7a !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-section="html"] .cm-editor .cm-selectionBackground,
|
body[data-section="html"] .cm-editor .cm-selectionBackground,
|
||||||
body[data-section="html"] .cm-editor .cm-content ::selection {
|
body[data-section="html"] .cm-editor .cm-content ::selection {
|
||||||
background-color: rgba(212, 99, 123, 0.25) !important;
|
background-color: rgba(199, 91, 122, 0.25) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-section="html"] .cm-editor .cm-activeLine {
|
body[data-section="html"] .cm-editor .cm-activeLine {
|
||||||
background-color: rgba(212, 99, 123, 0.08) !important;
|
background-color: rgba(199, 91, 122, 0.08) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-section="tailwind"] .cm-editor .cm-content {
|
body[data-section="tailwind"] .cm-editor .cm-content {
|
||||||
@@ -3012,12 +3067,12 @@ body[data-section="css"] .module-pill .level-indicator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body[data-section="html"] .module-pill {
|
body[data-section="html"] .module-pill {
|
||||||
background: rgba(212, 99, 123, 0.1);
|
background: rgba(199, 91, 122, 0.1);
|
||||||
color: #d4637b;
|
color: #c75b7a;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-section="html"] .module-pill .level-indicator {
|
body[data-section="html"] .module-pill .level-indicator {
|
||||||
color: #b84d63;
|
color: #a84862;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-section="tailwind"] .module-pill {
|
body[data-section="tailwind"] .module-pill {
|
||||||
@@ -3035,7 +3090,7 @@ body[data-section="css"] .code-block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body[data-section="html"] .code-block {
|
body[data-section="html"] .code-block {
|
||||||
border-color: rgba(212, 99, 123, 0.4);
|
border-color: rgba(199, 91, 122, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-section="tailwind"] .code-block {
|
body[data-section="tailwind"] .code-block {
|
||||||
@@ -3061,7 +3116,7 @@ body[data-section="tailwind"] .code-block .cm-editor .cm-line {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[data-section="html"] .task-instruction {
|
[data-section="html"] .task-instruction {
|
||||||
background: rgba(212, 99, 123, 0.92);
|
background: rgba(199, 91, 122, 0.92);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-section="tailwind"] .task-instruction {
|
[data-section="tailwind"] .task-instruction {
|
||||||
@@ -3074,7 +3129,7 @@ body[data-section="css"] .section-progress-bar .progress-fill {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body[data-section="html"] .section-progress-bar .progress-fill {
|
body[data-section="html"] .section-progress-bar .progress-fill {
|
||||||
background: #d4637b;
|
background: #c75b7a;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-section="tailwind"] .section-progress-bar .progress-fill {
|
body[data-section="tailwind"] .section-progress-bar .progress-fill {
|
||||||
@@ -3087,23 +3142,28 @@ body[data-section="tailwind"] .section-progress-bar .progress-fill {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[data-section="html"] .section-hero h1 {
|
[data-section="html"] .section-hero h1 {
|
||||||
color: #d4637b;
|
color: #c75b7a;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-section="tailwind"] .section-hero h1 {
|
[data-section="tailwind"] .section-hero h1 {
|
||||||
color: #26a69a;
|
color: #26a69a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reference footer */
|
/* Section and Reference footer - override landing-footer styles */
|
||||||
.reference-footer {
|
.section-footer.landing-footer,
|
||||||
text-align: center;
|
.reference-footer.landing-footer {
|
||||||
padding: 2rem 1rem;
|
max-width: 900px;
|
||||||
margin-top: 3rem;
|
margin: 6rem auto 0;
|
||||||
border-top: 1px solid var(--border-color);
|
padding: 0 var(--spacing-lg) var(--spacing-lg);
|
||||||
color: var(--light-text);
|
border-top: none;
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.reference-footer a {
|
.section-footer .footer-links a,
|
||||||
|
.reference-footer .footer-links a {
|
||||||
|
color: var(--light-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-footer .footer-links a:hover,
|
||||||
|
.reference-footer .footer-links a:hover {
|
||||||
color: var(--section-color, var(--primary-color));
|
color: var(--section-color, var(--primary-color));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user