Skip to content

Commit cee6899

Browse files
authored
Merge pull request #25 from ThePythonLedger/feature/add-memorygraph-support
Updated MemoryDebug components
2 parents eb5a2f9 + 4686b7f commit cee6899

5 files changed

Lines changed: 134 additions & 101 deletions

File tree

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,24 @@
1-
import React, { useMemo } from 'react';
1+
import React from 'react';
22
import MDXComponents from '@theme-original/MDXComponents';
3+
import MemoryGraphHeader from '@site/src/components/MemoryGraphHeader';
34
import styles from './styles.module.css';
45

5-
const MEMORY_GRAPH_BASE_URL = 'https://memory-graph.com/';
6-
76
/**
8-
* Wraps a ```lang debug code block with a header bar linking out to
9-
* Bas Terwijn's Memory Graph web debugger (memory-graph.com), so students
10-
* can step through the exact snippet from the lesson and watch variables/
11-
* references change line by line.
12-
*
13-
* Unlike InteractivePython, this doesn't replace the block with an editor —
14-
* the theme's normal <pre> still renders (syntax highlighting, copy button,
15-
* line numbers all keep working). We just read the raw code to build a
16-
* deep link and drop a button above it.
7+
* Wraps a ```lang debug (debug-only) code block: a flush MemoryGraphHeader
8+
* sitting directly on top of the theme's normal <pre>, so syntax
9+
* highlighting and the built-in copy button keep working.
1710
*
18-
* Memory Graph reads code from a URL *fragment* (`#code=...`), not a query
19-
* string — that's deliberate on their end, it means the code never gets
20-
* sent to their server, it's only ever interpreted client-side once the
21-
* page loads. Don't "fix" this to `?code=`.
11+
* For ```lang interactive debug (both keywords), MDXComponents renders
12+
* MemoryGraphHeader directly above InteractivePython instead, skipping
13+
* this component entirely — see src/theme/MDXComponents.js.
2214
*/
2315
export default function MemoryGraphBlock(props) {
24-
const { children } = props;
25-
const rawCode = children?.props?.children?.trim() || '';
26-
27-
const memoryGraphUrl = useMemo(
28-
() => `${MEMORY_GRAPH_BASE_URL}#code=${encodeURIComponent(rawCode)}`,
29-
[rawCode]
30-
);
16+
const rawCode = props.children?.props?.children || '';
3117

3218
return (
3319
<div className={styles.wrapper}>
34-
<div className={styles.header}>
35-
<span className={styles.headerText}>Debug Mode</span>
36-
<a
37-
href={memoryGraphUrl}
38-
target="_blank"
39-
rel="noopener noreferrer"
40-
className={styles.openButton}
41-
>
42-
Open in Memory Graph ↗
43-
</a>
44-
</div>
20+
<MemoryGraphHeader code={rawCode} flush />
4521
<MDXComponents.pre {...props} />
4622
</div>
4723
);
48-
}
24+
}
Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,11 @@
1-
/* ==========================================================================
2-
Reuses the site's existing purple accent (see .alert--explore in
3-
custom.css) so "debug" blocks read as their own category, distinct
4-
from the blue InteractivePython header.
5-
========================================================================== */
61
.wrapper {
72
margin: 1.5rem 0;
83
}
94

10-
.header {
11-
display: flex;
12-
align-items: center;
13-
justify-content: space-between;
14-
flex-wrap: wrap;
15-
gap: 12px;
16-
padding: 10px 16px;
17-
background-color: rgba(124, 58, 237, 0.08);
18-
border: 1px solid rgba(124, 58, 237, 0.35);
19-
border-bottom: none;
20-
border-radius: var(--ifm-global-radius) var(--ifm-global-radius) 0 0;
21-
}
22-
23-
[data-theme='dark'] .header {
24-
background-color: rgba(168, 85, 247, 0.15);
25-
border-color: rgba(216, 180, 254, 0.3);
26-
}
27-
28-
.headerText {
29-
font-family: var(--ifm-font-family-base, sans-serif);
30-
font-weight: 600;
31-
font-size: 0.85rem;
32-
letter-spacing: 0.05rem;
33-
text-transform: uppercase;
34-
color: #7c3aed;
35-
}
36-
37-
[data-theme='dark'] .headerText {
38-
color: #e9d5ff;
39-
}
40-
41-
.openButton {
42-
display: inline-flex;
43-
align-items: center;
44-
gap: 6px;
45-
padding: 6px 14px;
46-
border-radius: 6px;
47-
background-color: #7c3aed;
48-
color: #ffffff !important; /* override Docusaurus's default link color */
49-
font-family: var(--ifm-font-family-base, sans-serif);
50-
font-weight: 600;
51-
font-size: 0.85rem;
52-
text-decoration: none !important;
53-
white-space: nowrap;
54-
transition: background-color 0.15s ease;
55-
}
56-
57-
.openButton:hover {
58-
background-color: #6d28d9;
59-
color: #ffffff !important;
60-
}
61-
625
/* Butt the code block directly against the header — no gap, no double border */
636
.wrapper :global(.theme-code-block) {
647
margin-top: 0 !important;
658
border-top-left-radius: 0 !important;
669
border-top-right-radius: 0 !important;
6710
border-top: none !important;
6811
}
69-
70-
@media (max-width: 480px) {
71-
.header {
72-
justify-content: center;
73-
text-align: center;
74-
}
75-
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import React, { useMemo } from 'react';
2+
import styles from './styles.module.css';
3+
4+
const MEMORY_GRAPH_BASE_URL = 'https://memory-graph.com/';
5+
6+
/**
7+
* Purple header bar linking a code snippet out to Bas Terwijn's Memory
8+
* Graph web debugger (memory-graph.com). This is just the bar + link —
9+
* it doesn't render the code itself, so it can sit above either a plain
10+
* <pre> (```lang debug, via MemoryGraphBlock) or InteractivePython's
11+
* editable sandbox (```lang interactive debug, via MDXComponents).
12+
*
13+
* `code` is the raw (untrimmed is fine) source string; `flush` squares
14+
* off the bottom edge and drops the outer margin so it butts directly
15+
* against whatever renders right beneath it, instead of floating as its
16+
* own rounded pill.
17+
*/
18+
export default function MemoryGraphHeader({ code, flush = false }) {
19+
const memoryGraphUrl = useMemo(
20+
() => `${MEMORY_GRAPH_BASE_URL}#code=${encodeURIComponent((code || '').trim())}`,
21+
[code]
22+
);
23+
24+
return (
25+
<div className={`${styles.header} ${flush ? styles.flush : ''}`}>
26+
<span className={styles.headerText}>Debug Mode</span>
27+
<a
28+
href={memoryGraphUrl}
29+
target="_blank"
30+
rel="noopener noreferrer"
31+
className={styles.openButton}
32+
>
33+
View on Memory Graph ↗
34+
</a>
35+
</div>
36+
);
37+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* ==========================================================================
2+
Reuses the site's existing purple accent (see .alert--explore in
3+
custom.css) so "debug" blocks read as their own category, distinct
4+
from the blue InteractivePython header.
5+
========================================================================== */
6+
.header {
7+
display: flex;
8+
align-items: center;
9+
justify-content: space-between;
10+
flex-wrap: wrap;
11+
gap: 12px;
12+
margin: 1.5rem 0 0.5rem;
13+
padding: 10px 16px;
14+
background-color: rgba(124, 58, 237, 0.08);
15+
border: 1px solid rgba(124, 58, 237, 0.35);
16+
border-radius: var(--ifm-global-radius);
17+
}
18+
19+
[data-theme='dark'] .header {
20+
background-color: rgba(168, 85, 247, 0.15);
21+
border-color: rgba(216, 180, 254, 0.3);
22+
}
23+
24+
/* Flush mode: sits directly on top of a following block (a plain <pre>
25+
via MemoryGraphBlock) — squared-off bottom, no gap beneath it. The
26+
parent wrapper supplies the outer margin instead. */
27+
.header.flush {
28+
margin: 0;
29+
border-bottom: none;
30+
border-radius: var(--ifm-global-radius) var(--ifm-global-radius) 0 0;
31+
}
32+
33+
.headerText {
34+
font-family: var(--ifm-font-family-base, sans-serif);
35+
font-weight: 600;
36+
font-size: 0.85rem;
37+
letter-spacing: 0.05rem;
38+
text-transform: uppercase;
39+
color: #7c3aed;
40+
}
41+
42+
[data-theme='dark'] .headerText {
43+
color: #e9d5ff;
44+
}
45+
46+
.openButton {
47+
display: inline-flex;
48+
align-items: center;
49+
gap: 6px;
50+
padding: 6px 14px;
51+
border-radius: 6px;
52+
background-color: #7c3aed;
53+
color: #ffffff !important; /* override Docusaurus's default link color */
54+
font-family: var(--ifm-font-family-base, sans-serif);
55+
font-weight: 600;
56+
font-size: 0.85rem;
57+
text-decoration: none !important;
58+
white-space: nowrap;
59+
transition: background-color 0.15s ease;
60+
}
61+
62+
.openButton:hover {
63+
background-color: #6d28d9;
64+
color: #ffffff !important;
65+
}
66+
67+
@media (max-width: 480px) {
68+
.header {
69+
justify-content: center;
70+
text-align: center;
71+
}
72+
}

‎src/theme/MDXComponents.js‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,29 @@
11
import MDXComponents from '@theme-original/MDXComponents';
22
import InteractivePython from '@site/src/components/InteractivePython';
33
import MemoryGraphBlock from '@site/src/components/MemoryGraphBlock';
4+
import MemoryGraphHeader from '@site/src/components/MemoryGraphHeader';
45

56
export default {
67
...MDXComponents,
78
// We wrap the standard 'pre' tag (which wraps code blocks)
89
pre: (props) => {
910
const metastring = props.children?.props?.metastring || '';
11+
const isInteractive = metastring.includes('interactive');
12+
const isDebug = metastring.includes('debug');
1013

11-
if (metastring.includes('interactive')) {
14+
if (isInteractive && isDebug) {
15+
const rawCode = props.children?.props?.children || '';
16+
return (
17+
<>
18+
<MemoryGraphHeader code={rawCode} />
19+
<InteractivePython {...props} />
20+
</>
21+
);
22+
}
23+
if (isInteractive) {
1224
return <InteractivePython {...props} />;
1325
}
14-
if (metastring.includes('debug')) {
26+
if (isDebug) {
1527
return <MemoryGraphBlock {...props} />;
1628
}
1729
return <MDXComponents.pre {...props} />;

0 commit comments

Comments
 (0)