Skip to content

Commit 456b866

Browse files
authored
Merge pull request #7 from leftibot/fix/issue-6-add-wasm-playground
Fix #6: Add wasm playground
2 parents 940699b + 62f86f2 commit 456b866

File tree

4 files changed

+296
-0
lines changed

4 files changed

+296
-0
lines changed

.github/workflows/update-wasm.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Update WASM Playground
2+
3+
on:
4+
schedule:
5+
- cron: '17 * * * *'
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
update-wasm:
13+
name: Pull latest WASM artifacts
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Download WASM release assets
19+
env:
20+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
21+
run: |
22+
mkdir -p playground
23+
gh release download wasm-latest \
24+
--repo ChaiScript/ChaiScript \
25+
--pattern 'chaiscript.js' \
26+
--pattern 'chaiscript.wasm' \
27+
--dir playground \
28+
--clobber
29+
30+
- name: Check for changes
31+
id: changes
32+
run: |
33+
git add playground/
34+
if git diff --cached --quiet; then
35+
echo "changed=false" >> "$GITHUB_OUTPUT"
36+
else
37+
echo "changed=true" >> "$GITHUB_OUTPUT"
38+
fi
39+
40+
- name: Commit and push
41+
if: steps.changes.outputs.changed == 'true'
42+
run: |
43+
git config user.name "github-actions[bot]"
44+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
45+
git commit -m "Update WASM playground artifacts from ChaiScript/ChaiScript"
46+
git push

_includes/header.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
<li {% if page.url == '/examples.html'%} class='active' {% endif %}>
2727
<a href="/examples.html">Examples</a>
2828
</li>
29+
<li {% if page.url == '/playground.html'%} class='active' {% endif %}>
30+
<a href="/playground.html">Playground</a>
31+
</li>
2932
<li>
3033
<a href="https://github.com/ChaiScript/ChaiScript/blob/develop/cheatsheet.md">Cheatsheet</a>
3134
</li>

playground.html

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
---
2+
title: Playground
3+
---
4+
5+
<!DOCTYPE HTML>
6+
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
7+
8+
<head>
9+
10+
<title>ChaiScript - Interactive Playground</title>
11+
{% include common.html %}
12+
13+
<style>
14+
.playground-wrap {
15+
display: flex;
16+
gap: 0;
17+
min-height: 500px;
18+
border: 1px solid #ddd;
19+
border-radius: 4px;
20+
overflow: hidden;
21+
}
22+
.playground-panel {
23+
flex: 1;
24+
display: flex;
25+
flex-direction: column;
26+
min-width: 0;
27+
}
28+
.playground-panel-header {
29+
background: #f5f5f5;
30+
padding: 6px 12px;
31+
font-size: 0.8rem;
32+
text-transform: uppercase;
33+
letter-spacing: 0.1em;
34+
color: #888;
35+
border-bottom: 1px solid #ddd;
36+
}
37+
.playground-divider {
38+
width: 2px;
39+
background: #ddd;
40+
}
41+
#chai-input {
42+
flex: 1;
43+
background: #fff;
44+
color: #333;
45+
border: none;
46+
padding: 12px;
47+
font-family: "SF Mono", "Fira Code", "Fira Mono", Menlo, Consolas, monospace;
48+
font-size: 0.9rem;
49+
line-height: 1.6;
50+
resize: none;
51+
outline: none;
52+
tab-size: 2;
53+
}
54+
#chai-output {
55+
flex: 1;
56+
background: #fafafa;
57+
padding: 12px;
58+
font-family: "SF Mono", "Fira Code", "Fira Mono", Menlo, Consolas, monospace;
59+
font-size: 0.9rem;
60+
line-height: 1.6;
61+
overflow-y: auto;
62+
white-space: pre-wrap;
63+
word-break: break-all;
64+
}
65+
.chai-output-line { color: #333; }
66+
.chai-output-error { color: #d9534f; }
67+
#chai-status { font-size: 0.85rem; }
68+
#chai-status.ready { color: #5cb85c; }
69+
#chai-status.loading { color: #f0ad4e; }
70+
#chai-status.error { color: #d9534f; }
71+
.playground-controls {
72+
margin-top: 10px;
73+
display: flex;
74+
gap: 8px;
75+
align-items: center;
76+
}
77+
.playground-controls .hint {
78+
margin-left: auto;
79+
font-size: 0.75rem;
80+
color: #999;
81+
}
82+
</style>
83+
84+
</head>
85+
86+
<body>
87+
88+
{% include header.html %}
89+
90+
<div class="well well-sm">
91+
<h3>Interactive Playground <span id="chai-status" class="loading">Loading&hellip;</span></h3>
92+
<p>Write ChaiScript code and run it directly in your browser using WebAssembly.</p>
93+
</div>
94+
95+
<div class="body-with-margin">
96+
<div class="playground-wrap">
97+
<div class="playground-panel">
98+
<div class="playground-panel-header">Input</div>
99+
<textarea id="chai-input" spellcheck="false">// Welcome to ChaiScript!
100+
// Write your code here and click Run (or press Ctrl+Enter).
101+
102+
def greet(name) {
103+
return "Hello, " + name + "!"
104+
}
105+
106+
print(greet("World"))
107+
print(greet("ChaiScript"))
108+
109+
// Math example
110+
def factorial(n) {
111+
if (n &lt;= 1) { return 1 }
112+
return n * factorial(n - 1)
113+
}
114+
115+
print("5! = " + to_string(factorial(5)))
116+
print("10! = " + to_string(factorial(10)))
117+
</textarea>
118+
</div>
119+
<div class="playground-divider"></div>
120+
<div class="playground-panel">
121+
<div class="playground-panel-header">Output</div>
122+
<div id="chai-output"></div>
123+
</div>
124+
</div>
125+
126+
<div class="playground-controls">
127+
<button id="btn-run" class="btn btn-danger" disabled>Run</button>
128+
<button id="btn-clear" class="btn btn-default">Clear</button>
129+
<span class="hint">Ctrl+Enter to run</span>
130+
</div>
131+
</div>
132+
133+
<script>
134+
var outputEl = document.getElementById('chai-output');
135+
var inputEl = document.getElementById('chai-input');
136+
var btnRun = document.getElementById('btn-run');
137+
var btnClear = document.getElementById('btn-clear');
138+
var statusEl = document.getElementById('chai-status');
139+
140+
function appendOutput(text, className) {
141+
var line = document.createElement('div');
142+
line.className = className || 'chai-output-line';
143+
line.textContent = text;
144+
outputEl.appendChild(line);
145+
outputEl.scrollTop = outputEl.scrollHeight;
146+
}
147+
148+
var Module = {
149+
print: function(text) {
150+
appendOutput(text);
151+
},
152+
printErr: function(text) {
153+
appendOutput(text, 'chai-output-error');
154+
},
155+
onRuntimeInitialized: function() {
156+
statusEl.textContent = 'Ready';
157+
statusEl.className = 'ready';
158+
btnRun.disabled = false;
159+
}
160+
};
161+
162+
function runCode() {
163+
var code = inputEl.value;
164+
if (!code.trim()) { return; }
165+
166+
appendOutput('> Running...', 'chai-output-line');
167+
try {
168+
Module.eval(code);
169+
} catch (e) {
170+
appendOutput('Error: ' + e.message, 'chai-output-error');
171+
}
172+
appendOutput('', 'chai-output-line');
173+
}
174+
175+
btnRun.addEventListener('click', runCode);
176+
btnClear.addEventListener('click', function() {
177+
outputEl.innerHTML = '';
178+
});
179+
180+
inputEl.addEventListener('keydown', function(e) {
181+
if (e.ctrlKey && e.key === 'Enter') {
182+
e.preventDefault();
183+
runCode();
184+
}
185+
if (e.key === 'Tab') {
186+
e.preventDefault();
187+
var start = this.selectionStart;
188+
var end = this.selectionEnd;
189+
this.value = this.value.substring(0, start) + ' ' + this.value.substring(end);
190+
this.selectionStart = this.selectionEnd = start + 2;
191+
}
192+
});
193+
</script>
194+
<script src="/playground/chaiscript.js"></script>
195+
196+
</body>

test_playground.sh

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/bin/bash
2+
# Regression test for issue #6: WASM playground
3+
# Validates that all required files exist and contain expected content.
4+
set -euo pipefail
5+
6+
REPO_ROOT="$(cd "$(dirname "$0")" && pwd)"
7+
FAIL=0
8+
9+
assert_file_exists() {
10+
if [ ! -f "$REPO_ROOT/$1" ]; then
11+
echo "FAIL: $1 does not exist"
12+
FAIL=1
13+
else
14+
echo "PASS: $1 exists"
15+
fi
16+
}
17+
18+
assert_file_contains() {
19+
if ! grep -q "$2" "$REPO_ROOT/$1" 2>/dev/null; then
20+
echo "FAIL: $1 does not contain '$2'"
21+
FAIL=1
22+
else
23+
echo "PASS: $1 contains '$2'"
24+
fi
25+
}
26+
27+
# 1. GitHub Actions workflow exists and runs hourly
28+
assert_file_exists ".github/workflows/update-wasm.yml"
29+
assert_file_contains ".github/workflows/update-wasm.yml" "schedule"
30+
assert_file_contains ".github/workflows/update-wasm.yml" "cron:"
31+
assert_file_contains ".github/workflows/update-wasm.yml" "wasm-latest"
32+
assert_file_contains ".github/workflows/update-wasm.yml" "ChaiScript/ChaiScript"
33+
34+
# 2. Playground page exists with required elements
35+
assert_file_exists "playground.html"
36+
assert_file_contains "playground.html" "chaiscript.js"
37+
assert_file_contains "playground.html" "Module"
38+
assert_file_contains "playground.html" "header.html"
39+
40+
# 3. Navigation includes playground link
41+
assert_file_contains "_includes/header.html" "playground"
42+
43+
if [ "$FAIL" -ne 0 ]; then
44+
echo ""
45+
echo "RESULT: SOME TESTS FAILED"
46+
exit 1
47+
fi
48+
49+
echo ""
50+
echo "RESULT: ALL TESTS PASSED"
51+
exit 0

0 commit comments

Comments
 (0)