Merge branch 'main' into gh-pages

This commit is contained in:
Parker TenBroeck 2026-01-13 18:57:39 -05:00
commit 54aab1bc40
2 changed files with 51 additions and 8 deletions

View file

@ -57,12 +57,20 @@ bus.on("automata/update", _ => {
bus.emit("highlight/all/remove", undefined);
})
function decoForKind(kind: HighlightKind): string {
return `cm-highlight-${kind}`;
}
bus.on("highlight/one/add", (highlight) => {
const key = asKey(highlight);
if (current.has(key)) {
current.get(key)!.count += 1;
} else {
current.set(key, { count: 1, ...highlight });
const cname = decoForKind(highlight.kind);
globalThis.document.querySelectorAll(`[highlight-span="${highlight.span[0]}:${highlight.span[1]}"]`).forEach(el => el.classList.add(cname))
bus.emit("highlight/update", undefined);
}
});
@ -73,6 +81,10 @@ bus.on("highlight/one/remove", (highlight) => {
value.count -= 1;
if (value.count === 0) {
current.delete(key);
const cname = decoForKind(highlight.kind);
globalThis.document.querySelectorAll(`[highlight-span="${highlight.span[0]}:${highlight.span[1]}"]`).forEach(el => el.classList.remove(cname))
bus.emit("highlight/update", undefined);
}
}
@ -80,6 +92,24 @@ bus.on("highlight/one/remove", (highlight) => {
bus.on("highlight/all/remove", (_) => {
if (current.size !== 0) {
current.clear();
const warning = decoForKind("warning");
const focus = decoForKind("focus");
const success = decoForKind("success");
const error = decoForKind("error");
globalThis.document.querySelectorAll(`[highlight-span"]`).forEach(el => {
el.classList.remove(warning)
el.classList.remove(focus)
el.classList.remove(success)
el.classList.remove(error)
})
bus.emit("highlight/update", undefined);
}
});
});
export function highlightable(span: Span, text: string): string{
return `<span class = "cm-highlight" highlight-span="${span[0]}:${span[1]}">${text}</span>`
}

View file

@ -1,14 +1,12 @@
import { bus } from "./bus.ts";
import { DELTA } from "./constants.ts";
import { highlightable } from "./highlight.ts";
import type { Sim } from "./simulation.ts";
import type { FaState } from "./simulation/fa.ts";
import type { PdaState } from "./simulation/pda.ts";
import type { TmState } from "./simulation/tm.ts";
type AnyState = {
repr: string;
path: readonly unknown[];
};
function renderFaPath(state: FaState, index: number) {
const details = document.createElement("details");
@ -30,7 +28,11 @@ function renderFaPath(state: FaState, index: number) {
const div = document.createElement("div");
div.className = "stepLine";
const step = state.path[i];
div.textContent = `${i + 1}. ${DELTA}(${step.from_state}, ${step.from_letter}) = ${step.state}`;
div.innerHTML = `${i + 1}. `
+ highlightable(step.function, `${DELTA}(${step.from_state})`)
+ " = "
+ highlightable(step.transition, step.state);
steps.appendChild(div);
}
@ -59,7 +61,11 @@ function renderPdaPath(state: PdaState, index: number) {
const div = document.createElement("div");
div.className = "stepLine";
const step = state.path[i];
div.textContent = `${i + 1}. ${DELTA}(${step.from_state}, ${step.from_letter}, , ${step.from_stack}) = (${step.state}, [ ${step.stack.join(" ")} ])`;
div.innerHTML = `${i + 1}. `
+ highlightable(step.function, `${DELTA}(${step.from_state}, ${step.from_letter}, , ${step.from_stack})`)
+ " = "
+ highlightable(step.transition, `(${step.state}, [ ${step.stack.join(" ")} ])`);
steps.appendChild(div);
}
@ -88,7 +94,13 @@ function renderTmPath(state: TmState, index: number) {
const div = document.createElement("div");
div.className = "stepLine";
const step = state.path[i];
div.textContent = `${i + 1}. ${DELTA}(${step.from_state}, ${step.from_symbol}) = (${step.state}, ${step.symbol}, ${step.direction})`;
div.setAttribute("highlight-span", "${}")
div.innerHTML = `${i + 1}. `
+ highlightable(step.function, `${DELTA}(${step.from_state}, ${step.from_symbol})`)
+ " = "
+ highlightable(step.transition, `(${step.state}, ${step.symbol}, ${step.direction})`);
console.log(div.innerHTML);
steps.appendChild(div);
}
@ -118,6 +130,7 @@ export function renderPaths(sim: Sim | undefined) {
const runningCount = document.getElementById("runningCount")!;
const rejectedCount = document.getElementById("rejectedCount")!;
acceptedEl.innerHTML = "";
runningEl.innerHTML = "";
rejectedEl.innerHTML = "";