Skip to content

Commit 51fd7e0

Browse files
committed
basic dm-playground embedding
1 parent 7ffa8fd commit 51fd7e0

File tree

4 files changed

+66
-6
lines changed

4 files changed

+66
-6
lines changed

book.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ src = "src"
77

88
[output.html]
99
default-theme = "dark"
10+
additional-js = ["theme/playground-embed.js"]
11+
additional-css = ["theme/playground-embed.css"]
1012

1113
#[output.html.fold]
1214
#enable = true

src/preprocessor.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ var/daytime = NIGHT // daytime = 1
2020

2121
There also exists a subset of defines called Macros. These are in the format: `#define Name(Parameters) Value`. These are basically like procs, but without the ability to have variables stored within. These are great for common operations, such as checking conditions.
2222

23-
```dm
24-
/// Returns true if given is a client
25-
#define isclient(x) istype(x, /client)
23+
```dm playground
24+
#define isred(x) (x.color == "#ff0000")
2625
27-
/proc/hello(client/bar)
28-
if (isclient(bar))
29-
world << "Hello there!"
26+
/proc/main()
27+
var/obj/dog = new /obj{color = "#ff0000"}
28+
if (isred(dog))
29+
world.log << "Hello there!"
3030
```
3131

3232
## #if / #elif / #else / #ifdef / #endif

theme/playground-embed.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/* Styles for DM Playground embeds */
2+
.dm-playground-container { resize: both; overflow: hidden; max-width: 100%; }
3+
.dm-playground-iframe { border: none; width: 100%; height: 100%; min-height: 200px; }

theme/playground-embed.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Replace marked ```dm playground code blocks with dm-playground embeds.
2+
(function(){
3+
function utf8ToBase64(str){
4+
var bytes = new TextEncoder().encode(str);
5+
var binary = String.fromCharCode.apply(null, Array.from(bytes));
6+
return btoa(binary);
7+
}
8+
function makePlaygroundURL(code){
9+
return 'https://play.dm-lang.org/?embed&code=' + encodeURIComponent(utf8ToBase64(code));
10+
}
11+
function createIframe(src){
12+
var ifr = document.createElement('iframe');
13+
ifr.src = src;
14+
ifr.className = 'dm-playground-iframe';
15+
return ifr;
16+
}
17+
18+
document.addEventListener('DOMContentLoaded', function(){
19+
const codeBlocks = Array.from(document.querySelectorAll('pre > code'));
20+
codeBlocks.forEach(function(code){
21+
const cls = code.className || '';
22+
const parentCls = code.parentElement && code.parentElement.className ? code.parentElement.className : '';
23+
if (cls.indexOf('language-dm') === -1) return;
24+
if (cls.indexOf('playground') === -1 && parentCls.indexOf('playground') === -1) return;
25+
26+
const codeText = code.textContent || '';
27+
var wrapper = document.createElement('div');
28+
wrapper.className = 'dm-playground-container';
29+
30+
try {
31+
var ifr = createIframe(makePlaygroundURL(codeText));
32+
// Auto-height: estimate based on code lines
33+
const lines = (codeText.match(/\n/g) || []).length + 1;
34+
const estimated = Math.min(Math.max(lines * 16 + 88, 200), 900);
35+
wrapper.style.height = estimated + 'px';
36+
wrapper.style.minHeight = '200px';
37+
wrapper.appendChild(ifr);
38+
} catch (e) {
39+
var err = document.createElement('div');
40+
wrapper.appendChild(err);
41+
}
42+
43+
// Replace the <pre> element with the playground wrapper
44+
var pre = code.parentElement;
45+
if (pre?.parentElement) {
46+
try {
47+
pre.parentElement.replaceChild(wrapper, pre);
48+
} catch (e) {
49+
// fallback: append after if replaceChild fails
50+
pre.parentElement.insertBefore(wrapper, pre.nextSibling);
51+
}
52+
}
53+
});
54+
});
55+
})();

0 commit comments

Comments
 (0)