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>