From 4eec6f8a2d600bcffdb70ca41a75939b837bb965 Mon Sep 17 00:00:00 2001 From: Tangent Wantwight <tangent128@gmail.com> Date: Wed, 26 Jul 2023 22:14:16 -0400 Subject: [PATCH] First step to rendering script: preprocess global escapes --- 3x5.js | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++---- helpers.js | 9 ++++++++ index.html | 1 + 3 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 helpers.js diff --git a/3x5.js b/3x5.js index be13602..db59db9 100644 --- a/3x5.js +++ b/3x5.js @@ -1,10 +1,38 @@ /** - * @typedef {object} Card - Basic unit of information, also an "actor" in the programming system + * @typedef {object} Card Basic unit of information, also an "actor" in the programming system * @property {number} id Unique identifier * @property {Record<string, string>} fields Key-value properties on the card * @property {string} code Eventually: a markdown string containing code, but for now, just code */ +/** + * @typedef {"action" | "render"} ScriptType "Mode" of the environment a script runs in; determines access to mutability features and such. + * + * "action": response to a UI action; allowed to modify card fields and access time and random numbers. + * + * "render": deterministic generation of display markup from card and workspace state; can only modify temporary variables. + */ +/** + * @typedef {object} Vm State for running a script in. + * @property {ScriptType} mode Mutability status + * @property {string} output Markup to render / output + */ + +/** + * @param {Vm} state VM state + * @param {string} code Script to run + * @returns {string} Markup to render / output + */ +function renderCard(state, code) { + /* Preprocess: fold line endings */ + code = code.replace(/(?<!\\)(\\\\)*\\q/g, "$1"); + /* Preprocess: escape HTML */ + code = escapeHtml(code); + + state.output = code; + return state.output; +} + /** * Global state: a single card * @type {Card} @@ -16,7 +44,7 @@ let theCard = { h1 Hello, World! para [2 + 2] block { - This is a paragraph of text, with one [b bold] word. Yes, this means there has to be some magic in text processing... + This is a paragraph of text, with one [b bold] word. Yes, this means there has to be some magic in text processing... <b>this</b> won't work. } block -red "Beware!" para "All text should be quoted, it's clearer that way. & blockquotes already should contain paragraphs. (maybe normalize nested paragraphs)" @@ -31,16 +59,45 @@ let theCard = { } { Since we want escapes to work, these blocks [i will] be subject to substitutions. } + para { + line endings escaped\ + one slash + + not escaped if \\ + two slashes + + escaped with a slash if \\\ + three slashes + + not escaped with two slashes if \\\\ + four slashes + + escaped with two slashes if \\\\\ + five slashes + + not escaped with three slashes if \\\\\\ + six slashes + } `, }; const state = document.createElement("pre"); const display = document.createElement("blockquote"); +const debugDisplay = document.createElement("pre"); function render() { + const html = renderCard( + { + mode: "render", + output: "", + }, + theCard.code + ); + state.textContent = JSON.stringify(theCard, null, 2); - display.innerHTML = "<em>Rendering not implemented</em>"; + display.innerHTML = html; + debugDisplay.textContent = html; } render(); -document.body.append(state, display); +document.body.append(state, display, debugDisplay); diff --git a/helpers.js b/helpers.js new file mode 100644 index 0000000..a41c47a --- /dev/null +++ b/helpers.js @@ -0,0 +1,9 @@ +const escapeDiv = document.createElement("div"); +/** + * @param {string} text Potentially dangerous text + * @returns {string} Text safe to embed in HTML + **/ +function escapeHtml(text) { + escapeDiv.textContent = text; + return escapeDiv.innerHTML; +} diff --git a/index.html b/index.html index 9ae30dd..e9cad93 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ <meta charset="UTF-8" /> </head> <body> + <script src="helpers.js"></script> <script src="3x5.js"></script> </body> </html>