Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ x86-ubuntu-gpu-ml-isca.gz
build/

*.DS_Store

# node_modules
node_modules/
package-lock.json
35 changes: 35 additions & 0 deletions marp-custom-engine.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const { Marp } = require('@marp-team/marp-core');

// Define your variables here
const variables = {
BOOTCAMP_WEBSITE: "https://gem5bootcamp.gem5.org/",
BOOTCAMP_ARCHIVE: "https://gem5bootcamp.github.io/2024",
GITHUB_REPO: "https://github.com/gem5bootcamp/2024",
GITHUB_CLASSROOM: "https://classroom.github.com/a/gCcXlgBs",
GEM5_CODE: "https://github.com/gem5/gem5",
GEM5_WEBSITE: "https://www.gem5.org/",
GEM5_YOUTUBE: "https://youtube.com/@gem5",
GEM5_SLACK: "https://gem5-workspace.slack.com/join/shared_invite/zt-2e2nfln38-xsIkN1aRmofRlAHOIkZaEA"
};

// Function to replace placeholders with actual values in the markdown content
function replaceVariables(content) {
let updatedContent = content.toString(); // Ensure content is a string
for (const [key, value] of Object.entries(variables)) {
const placeholder = `{{${key}}}`;
const regex = new RegExp(placeholder, 'g');
updatedContent = updatedContent.replace(regex, value);
}
return updatedContent;
}

// Custom Marp engine class
class CustomMarpEngine extends Marp {
// Override the render method to preprocess Markdown content
render(markdown, options = {}) {
const processedMarkdown = replaceVariables(markdown); // Replace placeholders
return super.render(processedMarkdown, options); // Call Marp's render method
}
}

module.exports = CustomMarpEngine;
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"dependencies": {
"@marp-team/marp-cli": "^4.0.3",
"fs": "^0.0.1-security"
}
}
4 changes: 2 additions & 2 deletions slides/01-Introduction/00-introduction-to-bootcamp.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ author: Jason Lowe-Power

## About the overall structure of the bootcamp

These slides and are available at <https://bootcamp.gem5.org/> for you to follow along.
These slides and are available at {{BOOTCAMP_WEBSITE}} for you to follow along.

(Note: They will be archived at <https://gem5bootcamp.github.io/2024>)
(Note: They will be archived at {{GITHUB_REPO}})

The source for the slides, and what you'll be using throughout the bootcamp can be found on github at <https://github.com/gem5bootcamp/2024>

Expand Down
136 changes: 136 additions & 0 deletions web/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ const pdf_url_base = './pdf/'
const pdf_url_ext = '.pdf'
const slide_link_height = 25;

/* Button Names variables */
SHOW_SOLUTION_BUTTON_TEXT = "Show Solution";
HIDE_SOLUTION_BUTTON_TEXT = "Hide Solution";

/* Global references and variables */
let slide_list = [];
let slide_id = -1;
Expand Down Expand Up @@ -119,6 +123,138 @@ function sidebar_category_onclick(e) {
slides.style.height = `${height}px`;
}

/* ========================================================================= *
* Copy functionality
* ========================================================================= */
function addCopyButtonsInIframe() {
let frame = document.querySelector('#slideFrame');
if (!frame) {
console.error("Error: #slideFrame element not found.");
return;
}

// Function to insert copy buttons in <marp-pre><code> blocks inside the iframe
const insertCopyButtons = () => {
const frame = document.querySelector('#slideFrame');
const codeBlocks = frame.contentDocument.querySelectorAll('marp-pre code');

codeBlocks.forEach((block) => {
if (block.parentElement.querySelector('.copy-button')) return; // Avoid duplicates

// Create the copy button element
let copyButton = document.createElement('button');
copyButton.classList.add('copy-button');
copyButton.innerHTML = `<svg width="26px" height="26px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.24 2H11.3458C9.58159 1.99999 8.18418 1.99997 7.09054 2.1476C5.96501 2.29953 5.05402 2.61964 4.33559 3.34096C3.61717 4.06227 3.29833 4.97692 3.14701 6.10697C2.99997 7.205 2.99999 8.60802 3 10.3793V16.2169C3 17.725 3.91995 19.0174 5.22717 19.5592C5.15989 18.6498 5.15994 17.3737 5.16 16.312L5.16 11.3976L5.16 11.3024C5.15993 10.0207 5.15986 8.91644 5.27828 8.03211C5.40519 7.08438 5.69139 6.17592 6.4253 5.43906C7.15921 4.70219 8.06404 4.41485 9.00798 4.28743C9.88877 4.16854 10.9887 4.1686 12.2652 4.16867L12.36 4.16868H15.24L15.3348 4.16867C16.6113 4.1686 17.7088 4.16854 18.5896 4.28743C18.0627 2.94779 16.7616 2 15.24 2Z" fill="#007BFF"/>
<path d="M6.6001 11.3974C6.6001 8.67119 6.6001 7.3081 7.44363 6.46118C8.28716 5.61426 9.64481 5.61426 12.3601 5.61426H15.2401C17.9554 5.61426 19.313 5.61426 20.1566 6.46118C21.0001 7.3081 21.0001 8.6712 21.0001 11.3974V16.2167C21.0001 18.9429 21.0001 20.306 20.1566 21.1529C19.313 21.9998 17.9554 21.9998 15.2401 21.9998H12.3601C9.64481 21.9998 8.28716 21.9998 7.44363 21.1529C6.6001 20.306 6.6001 18.9429 6.6001 16.2167V11.3974Z" fill="#007BFF"/>
</svg>`;

// Set the CSS position directly with JavaScript
copyButton.style.position = 'absolute';
copyButton.style.top = '2px';
copyButton.style.right = '2px';
copyButton.style.background = 'none';
copyButton.style.border = 'none';
copyButton.style.padding = '4px';
copyButton.style.cursor = 'pointer';
copyButton.style.opacity = '0.7';

// Apply position to the <marp-pre> container
block.parentElement.style.position = 'relative';

// Insert the copy button at the beginning of each <marp-pre> element
block.parentElement.insertBefore(copyButton, block);

// Add the copy functionality
copyButton.addEventListener('click', () => {
navigator.clipboard.writeText(block.innerText);
});
});
};


// MutationObserver to detect changes within the iframe's content
const observer = new MutationObserver(insertCopyButtons);

// Listen for when the iframe content loads
frame.addEventListener('load', () => {
// Observe the iframe's document for added <marp-pre><code> blocks
observer.observe(frame.contentDocument.body, { childList: true, subtree: true });
insertCopyButtons(); // Initial call for existing code blocks
});
}

// Run addCopyButtonsInIframe after the main DOM is fully loaded
document.addEventListener('DOMContentLoaded', addCopyButtonsInIframe);

/* ========================================================================= *
* Hidden slides logic handeling
* ========================================================================= */
function setupToggleButtons() {
const frame = document.querySelector('#slideFrame');

// Check if iframe exists and load content
if (frame) {
frame.addEventListener('load', () => {
const contentDoc = frame.contentDocument || frame.contentWindow.document;

// Select all toggle buttons and toggle-content sections in the iframe
const toggleButtons = contentDoc.querySelectorAll('.toggle-button');
const toggleContents = contentDoc.querySelectorAll('.toggle-content');

// Force initial hidden state for all toggle-content elements
toggleContents.forEach(content => {
content.style.display = 'none'; // Ensure they are hidden at the start
});

// Initialize each button's text to "Show Content" and add inline styles
toggleButtons.forEach(button => {
button.textContent = SHOW_SOLUTION_BUTTON_TEXT;

// Apply inline styles to the toggle button
button.style.cursor = 'pointer';
button.style.backgroundColor = '#007bff'; // Blue color
button.style.color = 'white';
button.style.padding = '10px';
button.style.border = 'none';
button.style.borderRadius = '5px';
button.style.fontSize = '16px';
button.style.marginTop = '10px';

// Hover effect
button.addEventListener('mouseover', () => {
button.style.backgroundColor = '#0056b3'; // Darker blue on hover
});
button.addEventListener('mouseout', () => {
button.style.backgroundColor = '#007bff'; // Original blue
});
});

// Add click event listener to each toggle button
toggleButtons.forEach((button, index) => {
button.addEventListener('click', () => {
const content = toggleContents[index];
if (content) {
// Toggle the display of the content
if (content.style.display === 'none') {
content.style.display = 'block';
button.textContent = HIDE_SOLUTION_BUTTON_TEXT;
} else {
content.style.display = 'none';
button.textContent = SHOW_SOLUTION_BUTTON_TEXT;
}
}
});
});
});
} else {
console.error("Error: #slideFrame element not found.");
}
}

// Run setupToggleButtons after the main DOM is fully loaded
document.addEventListener('DOMContentLoaded', setupToggleButtons);

/* ========================================================================= *
* Relative Link to Git Translation !!TEMPORARY!!
* ========================================================================= */
Expand Down