From 3e629c6859a0ac916f966860e5eb1ee31b74fa23 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Mon, 1 Apr 2024 16:46:45 -0600 Subject: [PATCH] Re-adds workspaces (python IDE) --- LICENSE.md | 36 ++++- example-puzzles/example/7/boop.txt | 1 + example-puzzles/example/7/puzzle.md | 17 +++ theme/basic.css | 94 +++++++----- theme/config.json | 6 +- theme/fonts/Go-Mono.ttf | 1 + theme/fonts/Go-Regular.ttf | Bin 0 -> 140308 bytes theme/puzzle.css | 113 +++++++++++++++ theme/puzzle.html | 19 +++ theme/puzzle.mjs | 36 ++++- theme/workspace/python.mjs | 78 ++++++++++ theme/workspace/workspace.mjs | 214 ++++++++++++++++++++++++++++ 12 files changed, 568 insertions(+), 47 deletions(-) create mode 100644 example-puzzles/example/7/boop.txt create mode 100644 example-puzzles/example/7/puzzle.md create mode 100644 theme/fonts/Go-Mono.ttf create mode 100644 theme/fonts/Go-Regular.ttf create mode 100644 theme/puzzle.css create mode 100644 theme/workspace/python.mjs create mode 100644 theme/workspace/workspace.mjs diff --git a/LICENSE.md b/LICENSE.md index 82e110c..ecab0f3 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -129,10 +129,36 @@ Both came with the following license: > OTHER DEALINGS IN THE FONT SOFTWARE. -Javascript MD5 Library -====================== +Go Fonts +======= -Obtained from , which says: +The Go fonts were obtained from +https://go.googlesource.com/image -> The JavaScript MD5 script is released under the -> [MIT license](http://www.opensource.org/licenses/MIT). +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/example-puzzles/example/7/boop.txt b/example-puzzles/example/7/boop.txt new file mode 100644 index 0000000..8eb91f8 --- /dev/null +++ b/example-puzzles/example/7/boop.txt @@ -0,0 +1 @@ +Boop! diff --git a/example-puzzles/example/7/puzzle.md b/example-puzzles/example/7/puzzle.md new file mode 100644 index 0000000..c083655 --- /dev/null +++ b/example-puzzles/example/7/puzzle.md @@ -0,0 +1,17 @@ +--- +authors: + - neale +answers: + - 146 +attachments: + - boop.txt +--- + +Some puzzles can have embedded code. + +Your theme may turn this into a full in-browser development environment! + +```python +print(open("boop.txt").read()) +setanswer(0x58 + 58) +``` diff --git a/theme/basic.css b/theme/basic.css index 1ca2a37..1d5a4ce 100644 --- a/theme/basic.css +++ b/theme/basic.css @@ -1,12 +1,47 @@ /* Color palette: http://paletton.com/#uid=33x0u0klrl-4ON9dhtKtAdqMQ4T */ +:root { + --bg: #010e19; + --bg-main: #000d; + --heading: #cb2408cc; + --bg-heading1: #cb240844; + --fg-link: #b9cbd8; + --bg-input: #ccc4; + --bg-input-hover: #8884; + --bg-notification: #ac8f3944; + --bg-error: #f00; + --fg-error: white; + --bg-category: #ccc4; + --bg-input-invalid: #800; + --fg-input-invalid: white; + --bg-mothball: #ccc; + --bg-debug: #cccc; + --fg-debug: black; + --bg-toast: #333; + --fg-toast: #eee; + --box-toast: #0b0; +} + +@media (prefers-color-scheme: light) { + /* We uses the alpha channel to apply hue tinting to elements, to get a + * similar effect in light or dark mode. That means there aren't a whole lot of + * things to change between light and dark mode. + */ + :root { + --bg: #b9cbd8; + --fg: black; + --bg-main: #fffd; + --fg-link: #092b45; + } +} + body { font-family: sans-serif; - background: #010e19 url("bg.png") center fixed; + background: var(--bg) url("bg.png") center fixed; background-size: cover; background-blend-mode: soft-light; - background-color: #010e19; - color: #edd488; + background-color: var(--bg); + color: var(--fg); } canvas.wallpaper { position: fixed; @@ -24,20 +59,20 @@ main { margin: 1em auto; padding: 1px 3px; border-radius: 5px; - background: #000d; + background: var(--bg-main); } h1, h2, h3, h4, h5, h6 { - color: #cb2408cc; + color: var(--heading); } h1 { - background: #cb240844; + background: var(--bg-heading1); padding: 3px; } p { margin: 1em 0em; } a:any-link { - color: #b9cbd8; + color: var(--fg-link); } form, pre { margin: 1em; @@ -49,11 +84,11 @@ input, select { max-width: 30em; } input { - background-color: #ccc4; + background-color: var(--bg-input); color: inherit; } input:hover { - background-color: #8884; + background-color: var(--bg-input-hover); } input:active { background-color: inherit; @@ -63,11 +98,11 @@ input:active { border-radius: 8px; } .notification { - background: #ac8f3944; + background: var(--bg-notification); } .error { - background: red; - color: white; + background: var(--bg-error); + color: var(--fg-error); } .hidden { display: none; @@ -76,7 +111,7 @@ input:active { /** Puzzles list */ .category { margin: 5px 0; - background: #ccc4; + background: var(--bg-category); } .category h2 { margin: 0 0.2em; @@ -101,7 +136,7 @@ nav li, .category li { float: right; text-decoration: none; border-radius: 5px; - background: #ccc; + background: var(--bg-mothball); padding: 4px 8px; margin: 5px; } @@ -115,8 +150,8 @@ nav li, .category li { max-width: 100%; } input:invalid { - background-color: #800; - color: white; + background-color: var(--bg-input-invalid); + color: var(--fg-input-invalid); } .answer_ok { cursor: help; @@ -128,8 +163,8 @@ input:invalid { padding: 1em; border-radius: 10px; margin: 2em auto; - background: #cccc; - color: black; + background: var(--bg-debug); + color: var(--fg-debug); } .debug dt { font-weight: bold; @@ -173,28 +208,11 @@ li[draggable] { padding: 0.2em 2em; animation: fadeIn ease 1s; margin: 2px auto; - background: #333; - color: #eee; - box-shadow: 0px 0px 8px 0px #0b0; + background: var(--bg-toast); + color: var(--fg-toast); + box-shadow: 0px 0px 8px 0px var(--box-toast); } @keyframes fadeIn { 0% { opacity: 0; } 100% { opacity: 1; } } - -@media (prefers-color-scheme: light) { - /* We uses the alpha channel to apply hue tinting to elements, to get a - * similar effect in light or dark mode. That means there aren't a whole lot of - * things to change between light and dark mode. - */ - body { - background-color: #b9cbd8; - color: black; - } - main { - background-color: #fffd; - } - a:any-link { - color: #092b45; - } -} \ No newline at end of file diff --git a/theme/config.json b/theme/config.json index 8d4e3c4..4605a27 100644 --- a/theme/config.json +++ b/theme/config.json @@ -1,6 +1,10 @@ { "TrackSolved": true, "Titles": false, + "Puzzle": { + "SyntaxHighlighting": true, + "": 0 + }, "Scoreboard": { "DisplayServerURLWhenEnabled": true, "ShowCategoryLeaders": true, @@ -8,7 +12,7 @@ "ReplayFPS": 6, "ReplayDurationMS": 2000, "NoScoresHtml": "

~ no scores ~

", - "": "" + "": 0 }, "Messages": "", "": "this is here so you don't have to remember to take the comma off the last item" diff --git a/theme/fonts/Go-Mono.ttf b/theme/fonts/Go-Mono.ttf new file mode 100644 index 0000000..7cf65e0 --- /dev/null +++ b/theme/fonts/Go-Mono.ttf @@ -0,0 +1 @@ +font/gofont/ttfs/Go-Mono.ttf - image - Git at Google
blob: 853d473bebdf6d27eea9ddcc1f1d310483704229 [file] [log] [blame]
173248-byte binary file
\ No newline at end of file diff --git a/theme/fonts/Go-Regular.ttf b/theme/fonts/Go-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1b6ba86e38b613799742f81f467bed8dbc702f64 GIT binary patch literal 140308 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 szD`3@YC;#w99lom72qhz$apOO~Z1a#Tz|| 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 bYmc=v9F7ftH-D|FtzWQD`;BnbGJO9x + @@ -30,5 +31,23 @@

+ diff --git a/theme/puzzle.mjs b/theme/puzzle.mjs index 62fc689..f29a809 100644 --- a/theme/puzzle.mjs +++ b/theme/puzzle.mjs @@ -3,6 +3,7 @@ */ import * as moth from "./moth.mjs" import * as common from "./common.mjs" +import * as workspace from "./workspace/workspace.mjs" const server = new moth.Server(".") @@ -129,7 +130,7 @@ function writeObject(e, obj) { * @param {string} category * @param {number} points */ -async function loadPuzzle(category, points) { +async function loadPuzzle(category, points) { console.groupCollapsed("Loading puzzle:", category, points) let contentBase = new URL(`content/${category}/${points}/`, common.BaseURL) @@ -179,15 +180,41 @@ async function loadPuzzle(category, points) { } console.info("Listing attached files...") + let attachmentUrls = [] for (let fn of (puzzle.Attachments || [])) { let li = document.createElement("li") let a = document.createElement("a") - a.href = new URL(fn, contentBase) + let url = new URL(fn, contentBase) + attachmentUrls.push(url) + a.href = url a.innerText = fn li.appendChild(a) document.getElementById("files").appendChild(li) } + let codeBlocks = document.querySelectorAll("code[class^=language-]") + for (let i = 0; i < codeBlocks.length; i++) { + console.info(`Loading workspace ${i}...`) + let codeBlock = codeBlocks[i] + let language = "unknown" + let sourceCode = codeBlock.textContent + for (let c of codeBlock.classList) { + let parts = c.split("-") + if ((parts.length == 2) && parts[0].startsWith("lang")) { + language = parts[1] + } + } + + let id = category + "#" + points + "#" + i + let element = document.createElement("div") + let template = document.querySelector("template#workspace") + element.classList.add("workspace") + element.appendChild(template.content.cloneNode(true)) + element.workspace = new workspace.Workspace(element, id, sourceCode, language, attachmentUrls) + + // Now swap it in for the pre + codeBlock.parentElement.replaceWith(element) + } console.info("Filling debug information...") for (let e of document.querySelectorAll(".debug")) { @@ -199,7 +226,7 @@ async function loadPuzzle(category, points) { } window.app.puzzle = puzzle - console.info("window.app.puzzle =", window.app.puzzle) + console.info("window.app.puzzle:", window.app.puzzle) console.groupEnd() @@ -220,6 +247,9 @@ async function init() { // There isn't a more graceful way to "unload" scripts attached to the current puzzle window.addEventListener("hashchange", () => location.reload()) + // Workspaces may trigger a "this is the answer" event + document.addEventListener("setAnswer", e => SetAnswer(e.detail.value)) + // Make all links absolute, because we're going to be changing the base URL for (let e of document.querySelectorAll("[href]")) { e.href = new URL(e.href, common.BaseURL) diff --git a/theme/workspace/python.mjs b/theme/workspace/python.mjs new file mode 100644 index 0000000..50936d2 --- /dev/null +++ b/theme/workspace/python.mjs @@ -0,0 +1,78 @@ +import * as pyodide from "https://cdn.jsdelivr.net/npm/pyodide@0.25.1/pyodide.mjs" // v0.16.1 known good + +const HOME = "/home/web_user" + +async function createInstance() { + let instance = await pyodide.loadPyodide() + instance.runPython("import sys") + self.postMessage({type: "loaded"}) + return instance +} +const initialized = createInstance() + +class Buffer { + constructor() { + this.buf = [] + } + + write(s) { + this.buf.push(s) + } + + value() { + return this.buf.join("") + } +} + +async function handleMessage(event) { + let data = event.data + + let instance = await initialized + let fs = instance._module.FS + + let ret = { + result: null, + answer: null, + stdout: null, + stderr: null, + traceback: null, + } + + switch (data.type) { + case "nop": + // You might want to do nothing in order to display to the user that a run can now be handled + break + case "run": + let sys = instance.globals.get("sys") + sys.stdout = new Buffer() + sys.stderr = new Buffer() + instance.globals.set("setanswer", (s) => {ret.answer = s}) + + try { + ret.result = await instance.runPythonAsync(data.code) + } catch (err) { + ret.traceback = err + } + ret.stdout = sys.stdout.value() + ret.stderr = sys.stderr.value() + break + case "wget": + let url = data.url + let dir = data.directory || fs.cwd() + let filename = url.split("/").pop() + let path = dir + "/" + filename + + if (fs.analyzePath(path).exists) { + fs.unlink(path) + } + fs.createLazyFile(dir, filename, url, true, false) + break + default: + ret.result = "Unknown message type: " + data.type + break + } + if (data.channel) { + data.channel.postMessage(ret) + } +} +self.addEventListener("message", e => handleMessage(e)) diff --git a/theme/workspace/workspace.mjs b/theme/workspace/workspace.mjs new file mode 100644 index 0000000..b3ce2f7 --- /dev/null +++ b/theme/workspace/workspace.mjs @@ -0,0 +1,214 @@ +import {Toast} from "../common.mjs" +import "https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js" + +var workers = {} + +// loadWorker returns an existing worker if one exists, otherwise, it starts a new worker +function loadWorker(language) { + let worker = workers[language] + if (!worker) { + let url = new URL(language + ".mjs", import.meta.url) + worker = new Worker(url, { + type: "module", + }) + console.info("Loading worker", url, worker) + workers[language] = worker + } + return worker +} + +export class Workspace { + /** + * + * @param element {HTMLElement} Element to populate with the workspace + * @param id {string} A unique identifier of this workspace + * @param code {string} The "pristine" source code for this workspace + * @param language {string} The language for this workspace + * @param attachmentUrls {URL[]} List of attachment URLs + */ + constructor(element, id, code, language, attachmentUrls) { + this.element = element + this.originalCode = code + this.language = language + this.attachmentUrls = attachmentUrls + this.storageKey = "code:" + id + + // Get our document and window + this.document = this.element.ownerDocument + this.window = this.document.defaultView + + // Load user modifications, if there are any + this.code = localStorage[this.storageKey] || this.originalCode + + this.status = this.element.querySelector(".status") + this.linenos = this.element.querySelector(".editor .linenos") + this.editor = this.element.querySelector(".editor .text") + this.stdout = this.element.querySelector(".stdout") + this.stderr = this.element.querySelector(".stderr") + this.traceback = this.element.querySelector(".traceback") + this.stdinfo = this.element.querySelector(".stdinfo") + this.runButton = this.element.querySelector("button.run") + this.revertButton = this.element.querySelector("button.revert") + this.fontButton = this.element.querySelector("button.font") + + this.runButton.disabled = true + + // Load in the editor + this.editor.classList.add("language-" + language) + import("https://cdn.jsdelivr.net/npm/codejar@4.2.0").then((module) => this.editorReady(module)) + + // Load the interpreter + this.initLanguage(language) + + this.runButton.addEventListener("click", () => this.run()) + this.revertButton.addEventListener("click", () => this.revert()) + this.fontButton.addEventListener("click", () => this.font()) + } + + async initLanguage(language) { + let start = performance.now() + this.status.textContent = "Initializing..." + this.status.appendChild(document.createElement("progress")) + this.worker = loadWorker(language) + await this.workerReady() + + let runtime = performance.now() - start + let duration = new Date(runtime).toISOString().slice(11, -1) + this.status.textContent = "Loaded in " + duration + this.runButton.disabled = false + + for (let a of this.attachmentUrls) { + let filename = a.pathname.split("/").pop() + this.workerWget(a) + .then(ret => { + this.stdinfo.appendChild(this.document.createElement("div")).textContent = "Downloaded " + filename + }) + + } + } + + workerMessage(message) { + let chan = new MessageChannel() + message.channel = chan.port2 + this.worker.postMessage(message, [chan.port2]) + let p = new Promise( + (resolve, reject) => { + chan.port1.addEventListener("message", e => resolve(e.data), {once: true}) + } + ) + chan.port1.start() + return p + } + + workerReady() { + return this.workerMessage({type: "nop"}) + } + + workerWget(url) { + return this.workerMessage({ + type: "wget", + url: url.href || url, + }) + } + + /** + * highlight provides a code highlighter for CodeJar + * + * It calls Prism.highlightElement, then updates line numbers + */ + highlight(editor) { + if (Prism) { + // Sometimes it loads slowly + Prism.highlightElement(editor) + } else { + console.warn("No highlighter!", Prism, this.window.document.scripts) + } + + // Create a line numbers column + if (true) { + const code = editor.textContent || "" + const lines = code.split("\n") + let linesCount = lines.length + if (lines[linesCount-1]) { + linesCount += 1 + } + + let ltxt = "" + for (let i = 1; i < linesCount; i++) { + ltxt += i + "\n" + } + this.linenos.textContent = ltxt + } + } + + /** + * Called when the editor has imported + * + */ + editorReady(module) { + this.jar = module.CodeJar(this.editor, (editor) => this.highlight(editor), {window: this.window}) + this.jar.updateCode(this.code) + switch (this.language) { + case "python": + this.jar.updateOptions({ + tab: " ", + indentOn: /:$/, + }) + break + } + } + + setAnswer(answer) { + let evt = new CustomEvent("setAnswer", {detail: {value: answer}, bubbles: true, cancelable: true}) + this.element.dispatchEvent(evt) + + this.stdinfo.appendChild(this.document.createTextNode("Set answer to ")) + this.stdinfo.appendChild(this.document.createElement("code")).textContent = answer + } + + async run() { + let start = performance.now() + this.runButton.disabled = true + this.status.textContent = "Running..." + + // Save first. Always save first. + let program = this.jar.toString() + if (program != this.originalCode) { + localStorage[this.storageKey] = program + } + + let result = await this.workerMessage({ + type: "run", + code: program, + }) + + this.stdout.textContent = result.stdout + this.stderr.textContent = result.stderr + this.traceback.textContent = result.traceback + while (this.stdinfo.firstChild) this.stdinfo.firstChild.remove() + if (result.answer) { + this.setAnswer(result.answer) + } + + let runtime = performance.now() - start + let duration = new Date(runtime).toISOString().slice(11, -1) + this.status.textContent = "Ran in " + duration + this.runButton.disabled = false + } + + revert() { + let currentCode = this.jar.toString() + let savedCode = localStorage[this.storageKey] + if ((currentCode == this.originalCode) && savedCode) { + this.jar.updateCode(savedCode) + Toast("Re-loaded saved code") + } else { + this.jar.updateCode(this.originalCode) + Toast("Reverted to original code") + } + } + + font(force) { + this.element.classList.toggle("fixed", force) + } +}