diff --git a/tutorial/justfile b/tutorial/justfile
index 8d079dc8..9589856a 100644
--- a/tutorial/justfile
+++ b/tutorial/justfile
@@ -15,6 +15,10 @@ gpt_files_content:
tutorial-json_toc:
python scripts/convert_toc.py
+
+tutorial_prepare: tutorial-json_toc
+ cd single_page_book_app && npm install
+
tutorial_book:
cd jbook && rm -rf _build && export PYTHONPATH=$(pwd)/sphinx_ext_imgui && jupyter-book build .
diff --git a/tutorial/single_page_book_app/resources_singlepage/code_editor.js b/tutorial/single_page_book_app/resources_singlepage/code_editor.js
index 147bcbe9..8e951645 100644
--- a/tutorial/single_page_book_app/resources_singlepage/code_editor.js
+++ b/tutorial/single_page_book_app/resources_singlepage/code_editor.js
@@ -18,25 +18,10 @@ async function _processCodesIncludeInMarkdown(mdText, baseUrlPath) {
if (line.trim().startsWith("```{codes_include}")) {
const match = line.match(/```{codes_include}\s+(.*)/);
if (match) {
- console.log("Found codes_include directive:", match[1]); // Log matched directive
+ // console.log("Found codes_include directive:", match[1]); // Log matched directive
const baseName = match[1].trim();
// Generate HTML as a string
-// const tabsHtml = `
-//
-//
-//
-//
-//
-//
-//
`;
const tabsHtml = `
@@ -52,9 +37,7 @@ async function _processCodesIncludeInMarkdown(mdText, baseUrlPath) {
`;
-
-
- console.log("Generated HTML for tabs:", tabsHtml); // Debug log
+ // console.log("Generated HTML for tabs:", tabsHtml); // Debug log
processedLines.push(tabsHtml);
}
insideCodesIncludeBlock = true;
@@ -68,31 +51,37 @@ async function _processCodesIncludeInMarkdown(mdText, baseUrlPath) {
return processedLines.join("\n");
}
+
async function _initializeCodeMirrorEditors(baseUrlPath) {
const containers = document.querySelectorAll(".code-editor-tab-container");
- console.log("Found Code Editor Containers:", containers.length); // Debug log
+ // console.log("Found Code Editor Containers:", containers.length); // Debug log
for (const container of containers) {
const tabPanes = container.querySelectorAll(".code-editor-tab-pane");
- console.log("Found Tab Panes:", tabPanes.length); // Debug log
+ // console.log("Found Tab Panes:", tabPanes.length); // Debug log
for (const tabPane of tabPanes) {
const filePath = tabPane.dataset.file;
const language = tabPane.dataset.language.toLowerCase();
- console.log(`Initializing CodeMirror for file: ${filePath}, language: ${language}`); // Debug log
+ // console.log(`Initializing CodeMirror for file: ${filePath}, language: ${language}`); // Debug log
try {
- const fileResponse = await fetch(`${baseUrlPath}${filePath}`);
+ // Correctly handle baseUrlPath and filePath to avoid duplication
+ // Relative path; combine with baseUrlPath
+ let fullPath = new URL(filePath, `${window.location.origin}/${baseUrlPath}/`).toString();
+ // console.log(`Full Path for Fetch: ${fullPath}`); // Debug log
+
+ const fileResponse = await fetch(fullPath);
if (!fileResponse.ok) {
- console.warn(`File not found: ${baseUrlPath}${filePath}`);
+ console.warn(`File not found: ${fullPath}`);
continue;
}
const codeContent = await fileResponse.text();
- console.log(`Fetched Code Content for ${filePath}:\n`, codeContent); // Debug log
+ // console.log(`Fetched Code Content for ${filePath}:\n`, codeContent); // Debug log
const cmPlaceholder = tabPane.querySelector(".codemirror-placeholder");
@@ -129,16 +118,17 @@ async function _initializeCodeMirrorEditors(baseUrlPath) {
_setupCodeEditorTabs(containers); // Ensure tab setup is called
}
+
function _setupCodeEditorTabs(containers) {
containers.forEach((container) => {
const buttons = container.querySelectorAll(".code-editor-tab-button");
const panes = container.querySelectorAll(".code-editor-tab-pane");
buttons.forEach((button) => {
- console.log(`Attaching click event to button: ${button.dataset.tab}`); // Debugging log
+ // console.log(`Attaching click event to button: ${button.dataset.tab}`); // Debugging log
button.addEventListener("click", () => {
const targetTab = button.dataset.tab;
- console.log(`Tab clicked: ${targetTab}`); // Debugging log
+ // console.log(`Tab clicked: ${targetTab}`); // Debugging log
// Deactivate all buttons and panes
buttons.forEach((btn) => btn.classList.remove("active"));
@@ -191,12 +181,13 @@ export async function prepareCodeEditors(mdText, baseUrlPath) {
const renderedHtml = marked(processedMdText);
// Debug log: Final rendered HTML
- console.log("Final Rendered HTML:", renderedHtml);
+ // console.log("Final Rendered HTML:", renderedHtml);
// Update the content area with the rendered HTML
const contentArea = document.getElementById("content-area");
contentArea.innerHTML = renderedHtml;
// Initialize CodeMirror editors for the placeholders
- await _initializeCodeMirrorEditors(baseUrlPath);
+ //await _initializeCodeMirrorEditors(baseUrlPath);
+ await _initializeCodeMirrorEditors("jbook");
}
diff --git a/tutorial/single_page_book_app/resources_singlepage/style.css b/tutorial/single_page_book_app/resources_singlepage/style.css
index 921c0aa7..116c4d56 100644
--- a/tutorial/single_page_book_app/resources_singlepage/style.css
+++ b/tutorial/single_page_book_app/resources_singlepage/style.css
@@ -248,60 +248,73 @@ body {
/* ==========================
Code Editor Tabs
========================== */
+
.code-editor-tab-container {
- border: 1px solid #ccc;
+ border: 1px solid #007bff; /* Blue border for the container */
border-radius: 4px;
overflow: hidden;
margin-bottom: 1rem;
- background-color: #f9f9f9;
+ background-color: #ffffff;
}
.code-editor-tab-buttons {
display: flex;
- background-color: #f9f9f9;
+ justify-content: flex-start; /* Align tabs to the left */
+ padding: 0.2rem; /* Small padding around tabs */
+ background-color: #f9f9f9; /* Light gray for the tab bar */
border-bottom: 1px solid #ccc;
+ gap: 0.2rem; /* Add small gap between tabs */
}
.code-editor-tab-button {
- flex: 1;
- padding: 0.5rem;
- text-align: center;
- background-color: #e9ecef;
+ padding: 0.5rem 1rem; /* Adjust padding for a compact look */
border: none;
+ border-radius: 4px 4px 0 0; /* Rounded top corners */
+ background-color: #e9ecef; /* Light gray background for inactive tabs */
cursor: pointer;
- font-size: 1rem;
+ font-size: 0.9rem;
font-weight: bold;
+ color: #333; /* Neutral dark text for inactive tabs */
+ transition: background-color 0.3s, color 0.3s;
}
.code-editor-tab-button.active {
+ background-color: #007bff; /* Blue background for active tab */
+ color: white; /* White text for active tab */
font-weight: bold;
- background-color: #007bff;
- color: white;
- border-bottom: 2px solid white;
+ border-bottom: 2px solid #ffffff; /* Seamless transition to the content area */
}
.code-editor-tab-button:hover {
- background-color: #0056b3;
+ background-color: #0056b3; /* Darker blue on hover */
color: white;
}
.code-editor-tab-content {
- padding: 0;
- background-color: white;
+ padding: 1rem;
+ background-color: #ffffff; /* White background for content area */
+ border-top: none;
}
.code-editor-tab-pane {
- display: none; /* All panes are hidden by default */
- padding: 1rem;
+ display: block;
+ animation: fadeIn 0.2s ease-in; /* Smooth fade-in animation for content */
}
-.code-editor-tab-pane:not(.hidden) {
- display: block; /* Only the active pane is shown */
+.code-editor-tab-pane.hidden {
+ display: none;
}
-.code-editor-tab-button.active {
- background-color: #007bff;
- color: white;
+/* Subtle animation for tab switching */
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ transform: translateY(5px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
}
/* ==========================