From f4938d683f40ab2fee4e3f72febdde10f772dea1 Mon Sep 17 00:00:00 2001 From: Jason Cabot Date: Sun, 25 Feb 2024 17:46:05 +0000 Subject: [PATCH] Added bold, italic, underline and code formatting whilst printing text. Added example02 if you have the code for it --- .gitignore | 2 + internal/jabl/lexer.go | 11 +- .../testdata/examples/dynamic_goto/code.jabl | 7 ++ .../examples/dynamic_goto/result.json | 10 ++ .../examples/dynamic_goto/state_after.json | 3 + .../examples/dynamic_goto/state_before.json | 1 + .../testdata/examples/print_string/code.jabl | 2 + .../examples/print_string/result.json | 2 +- web/app.css | 4 + web/app.js | 104 ++++++++++++++++-- 10 files changed, 132 insertions(+), 14 deletions(-) create mode 100644 internal/jabl/testdata/examples/dynamic_goto/code.jabl create mode 100644 internal/jabl/testdata/examples/dynamic_goto/result.json create mode 100644 internal/jabl/testdata/examples/dynamic_goto/state_after.json create mode 100644 internal/jabl/testdata/examples/dynamic_goto/state_before.json diff --git a/.gitignore b/.gitignore index 735fe92..1ccf600 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ bin *.wasm .wrangler node_modules + +web/example02 \ No newline at end of file diff --git a/internal/jabl/lexer.go b/internal/jabl/lexer.go index 8fa1dad..2f5a93d 100644 --- a/internal/jabl/lexer.go +++ b/internal/jabl/lexer.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "strconv" + "strings" "text/scanner" "unicode" ) @@ -169,7 +170,15 @@ func (l *lexer) Lex(lval *yySymType) int { default: if text[0] == '"' && text[len(text)-1] == '"' { // trim the start and end quotes and add a newline - lval.String = text[1 : len(text)-1] + inner := text[1 : len(text)-1] + + // replace escaped characters + inner = strings.ReplaceAll(inner, "\\n", "\n") + inner = strings.ReplaceAll(inner, "\\t", "\t") + inner = strings.ReplaceAll(inner, "\\\"", "\"") + + lval.String = inner + return STRING } else if text == "true" { lval.Boolean = true diff --git a/internal/jabl/testdata/examples/dynamic_goto/code.jabl b/internal/jabl/testdata/examples/dynamic_goto/code.jabl new file mode 100644 index 0000000..5ddfc90 --- /dev/null +++ b/internal/jabl/testdata/examples/dynamic_goto/code.jabl @@ -0,0 +1,7 @@ +{ + goto(1d6 + ".jabl") + set("a", 1d6) + choice("a", { + goto(get("a") + 2d6 + ".jabl") + }) +} \ No newline at end of file diff --git a/internal/jabl/testdata/examples/dynamic_goto/result.json b/internal/jabl/testdata/examples/dynamic_goto/result.json new file mode 100644 index 0000000..44fb496 --- /dev/null +++ b/internal/jabl/testdata/examples/dynamic_goto/result.json @@ -0,0 +1,10 @@ +{ + "output": "", + "choices": [ + { + "text": "a", + "code": "{\n\tgoto(get(\"a\") + 2d6 + \".jabl\")\n}" + } + ], + "transition": "6.jabl" +} diff --git a/internal/jabl/testdata/examples/dynamic_goto/state_after.json b/internal/jabl/testdata/examples/dynamic_goto/state_after.json new file mode 100644 index 0000000..2728c9d --- /dev/null +++ b/internal/jabl/testdata/examples/dynamic_goto/state_after.json @@ -0,0 +1,3 @@ +{ + "a": 6 +} diff --git a/internal/jabl/testdata/examples/dynamic_goto/state_before.json b/internal/jabl/testdata/examples/dynamic_goto/state_before.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/internal/jabl/testdata/examples/dynamic_goto/state_before.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/internal/jabl/testdata/examples/print_string/code.jabl b/internal/jabl/testdata/examples/print_string/code.jabl index 5d1fd1a..e6c176b 100644 --- a/internal/jabl/testdata/examples/print_string/code.jabl +++ b/internal/jabl/testdata/examples/print_string/code.jabl @@ -2,4 +2,6 @@ print("hello world") print(("hello world")) print("hello" + " " + "world") + print("hello \"world\"") + print("hello\nworld") } \ No newline at end of file diff --git a/internal/jabl/testdata/examples/print_string/result.json b/internal/jabl/testdata/examples/print_string/result.json index 39e9e29..53bf54b 100644 --- a/internal/jabl/testdata/examples/print_string/result.json +++ b/internal/jabl/testdata/examples/print_string/result.json @@ -1,5 +1,5 @@ { - "output": "hello world\nhello world\nhello world\n", + "output": "hello world\nhello world\nhello world\nhello \"world\"\nhello\nworld\n", "choices": null, "transition": "" } diff --git a/web/app.css b/web/app.css index 64e7a67..5ad3f41 100644 --- a/web/app.css +++ b/web/app.css @@ -145,4 +145,8 @@ body { .option:hover { background-color: #023021; +} + +code { + background-color: #033827; } \ No newline at end of file diff --git a/web/app.js b/web/app.js index 140bf9d..c56cf45 100644 --- a/web/app.js +++ b/web/app.js @@ -11,11 +11,52 @@ const renderText = (text) => { intervalId = setInterval(() => { if (text && textIndex < text.length) { - if (text.charAt(textIndex) === "\n") { - consoleText.innerHTML += "

"; - } else { - consoleText.innerHTML += text.charAt(textIndex); + switch (text.charAt(textIndex)) { + case "\n": + consoleText.innerHTML += "

"; + break; + case "*": + let boldText = ""; + textIndex++; + while (text.charAt(textIndex) !== "*") { + boldText += text.charAt(textIndex); + textIndex++; + } + consoleText.innerHTML += `${boldText}`; + break; + case "_": + let underlineText = ""; + textIndex++; + while (text.charAt(textIndex) !== "_") { + underlineText += text.charAt(textIndex); + textIndex++; + } + consoleText.innerHTML += `${underlineText}`; + break; + case "`": + let codeText = ""; + textIndex++; + while (text.charAt(textIndex) !== "`") { + codeText += text.charAt(textIndex); + textIndex++; + } + consoleText.innerHTML += `${codeText}`; + break; + case "/": + let italicText = ""; + textIndex++; + while (text.charAt(textIndex) !== "/") { + italicText += text.charAt(textIndex); + textIndex++; + } + consoleText.innerHTML += `${italicText}`; + break; + default: + console.log(text.charAt(textIndex)); + consoleText.innerHTML += text.charAt(textIndex); + break; } + // scroll consoleText to the bottom of what it is displaying consoleText.parentElement.scrollTop = consoleText.parentElement.scrollHeight; @@ -24,6 +65,23 @@ const renderText = (text) => { clearInterval(intervalId); } }, 10); + + // can tap to skip the text animation + consoleText.onclick = () => { + if (text && textIndex < text.length) { + let html = text.replace(/\/([^/]+?)\//g, "$1"); + + html = html.replace(/\n/g, "

"); + html = html.replace(/\*([^\*]*?)\*/g, "$1"); + html = html.replace(/_([^_]+?)_/g, "$1"); + html = html.replace(/`([^`]+)`/g, "$1"); + + consoleText.innerHTML = html; + + clearInterval(intervalId); + textIndex = text.length; + } + }; }; const renderChoices = (choices) => { @@ -94,6 +152,25 @@ const run = async () => { } }; +const sources = [ + { + id: 1, + name: "Example 1", + url: "https://raw.githubusercontent.com/jasoncabot/fabled-story-book/main/assets/example01/", + entrypoint: "entrypoint.jabl", + }, + { + id: 2, + name: "Example 2", + url: "http://localhost:8788/example02/", + entrypoint: "0-choose-character.jabl", + }, +]; +const availableSources = sources.reduce((acc, source) => { + acc[source.id] = source.url; + return acc; +}, {}); + const registerGlobals = () => { window.bookStorage = { getItem: (key) => { @@ -120,7 +197,10 @@ const registerGlobals = () => { localStorage.removeItem(key); } } - localStorage.setItem("system:section", "entrypoint.jabl"); + const entrypoint = sources.find( + (source) => source.id == sourceId + )?.entrypoint; + localStorage.setItem("system:section", entrypoint); // And restart the game startSelection(); @@ -136,9 +216,7 @@ const registerGlobals = () => { }; window.loadSection = (identifier, callback) => { const sourceId = localStorage.getItem("system:source"); - const sourceURL = { - 1: "https://raw.githubusercontent.com/jasoncabot/fabled-story-book/main/assets/example01/", - }[sourceId]; + const sourceURL = availableSources[sourceId]; if (!sourceURL) { throw new Error("Invalid source id"); } @@ -165,13 +243,15 @@ const startSelection = () => { }; const showSelectionChoices = () => { + const choices = sources.map( + (source) => + `choice("${source.name}", { set("system:source", ${source.id}) goto("${source.entrypoint}")})` + ); + runJABL(`{ print("Welcome to the game!") print("Which book would you like to play?") - choice("Example 1", { - set("system:source", 1) - goto("entrypoint.jabl") - }) + ${choices.join("\n")} }`); };