From fa110998501975055fcad2b62e94f6586087d1b2 Mon Sep 17 00:00:00 2001 From: Tangent Wantwight Date: Mon, 20 Nov 2023 22:54:56 -0500 Subject: [PATCH] Interpolate text blocks in html helpers --- src/3x5.ts | 2 +- src/lib/html.ts | 26 +++++++++++++++++++++----- src/parser.ts | 14 ++++++++++++++ src/vm.ts | 2 +- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/3x5.ts b/src/3x5.ts index 3934999..07a4ba1 100644 --- a/src/3x5.ts +++ b/src/3x5.ts @@ -153,7 +153,7 @@ function triggerEvent(handlerPos: number) { const script = parse(theCard.code); if (script[0]) { - runNoctl(vm, script[1], (word) => {}); + runNoctl(vm, script[1]); } else { console.debug(script[1]); } diff --git a/src/lib/html.ts b/src/lib/html.ts index 1d49fd6..b6c2643 100644 --- a/src/lib/html.ts +++ b/src/lib/html.ts @@ -1,13 +1,29 @@ -import { AsHtml, Concat, ProcResult, TextPiece } from "../words"; -import { getOptRaw } from "./options"; +import { TemplateBlock } from '../parser'; +import { evaluateWord } from '../vm'; +import { AsHtml, Concat, ProcResult, TextPiece } from '../words'; +import { CardVm } from './card'; +import { getOptRaw } from './options'; const htmlBlockCmd = (tag: string) => - ({}, argv: TextPiece[]): ProcResult => - getOptRaw(argv, { $min: 1 }, (_opts, words) => { + (vm: CardVm, argv: TextPiece[]): ProcResult => + getOptRaw(argv, { $min: 1, raw: 0 }, ({ raw }, words) => { + function interpolate(word: TextPiece) { + if ("text" in word && !raw) { + const [tmplMatch] = TemplateBlock.match(word.text, 0); + if (tmplMatch) { + const result = evaluateWord(vm, tmplMatch[0]); + return AsHtml(result); + } else { + return AsHtml(word); + } + } else { + return AsHtml(word); + } + } return ( words - .map((word) => ({ html: `<${tag}>${AsHtml(word)}` })) + .map((word) => ({ html: `<${tag}>${interpolate(word)}` })) .reduce(Concat, null) ?? { html: "" } ); }); diff --git a/src/parser.ts b/src/parser.ts index bec8ff9..bed45bc 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -54,6 +54,20 @@ const QuotedWord = Sequence( Regex(/"/y).expects('"') ).map(([, pieces], pos) => SimplifyWord(pieces, pos)); +export const TemplateBlock = Sequence( + AtLeast( + 0, + Choose( + BackslashEscape, + Bracket, + Regex(/[^\\\[]+/y) + .expects("CHAR") + .map(([text]) => ({ text })) + ) + ), + End() +).map(([pieces], pos) => SimplifyWord(pieces, pos)); + const Brace: Pattern = Sequence( Regex(/\{/y).expects("{"), AtLeast( diff --git a/src/vm.ts b/src/vm.ts index 5a463db..8472422 100644 --- a/src/vm.ts +++ b/src/vm.ts @@ -30,7 +30,7 @@ export type Vm = { output: string; } & Context; -function evaluateWord( +export function evaluateWord( state: Vm, word: Word | InterpolatedPiece ): TextPiece | ErrorResult {