From 14b359462f1455cc4a6ddf1c191f4ca0ace167d4 Mon Sep 17 00:00:00 2001 From: Thomas Hallock Date: Mon, 10 Nov 2025 09:53:19 -0600 Subject: [PATCH] fix(worksheets): correct Typst array membership syntax for ten-frames rendering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix ten-frames not rendering on worksheets when scaffolding rules called for them. The issue was in the Typst template code using incorrect syntax for checking array membership. Typst requires `.contains(item)` method, not `(item in array)`. Changes: - typstHelpers.ts:203: Change `(i in regrouping-places)` to `regrouping-places.contains(i)` - answerRow.ts:52: Change `(i in borrow-places)` to `borrow-places.contains(i)` This was causing `shows-frame` to evaluate incorrectly, preventing ten-frames from rendering even when displayRules.tenFrames was set to 'whenRegrouping' and the problem had actual regrouping. Affects both addition and subtraction worksheets. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../worksheets/addition/typstHelpers.ts | 87 ++++++++----------- .../typstHelpers/subtraction/answerRow.ts | 18 ++-- 2 files changed, 46 insertions(+), 59 deletions(-) diff --git a/apps/web/src/app/create/worksheets/addition/typstHelpers.ts b/apps/web/src/app/create/worksheets/addition/typstHelpers.ts index 5458479e..c538ef3f 100644 --- a/apps/web/src/app/create/worksheets/addition/typstHelpers.ts +++ b/apps/web/src/app/create/worksheets/addition/typstHelpers.ts @@ -5,16 +5,16 @@ // for backward compatibility. New code should import from typstHelpers/ directly. // Import types for internal use -import type { DisplayOptions } from "./typstHelpers/shared/types"; +import type { DisplayOptions } from './typstHelpers/shared/types' // Re-export everything from modular structure export type { DisplayOptions, CellDimensions, -} from "./typstHelpers/shared/types"; -export { generateTypstHelpers } from "./typstHelpers/shared/helpers"; -export { generatePlaceValueColors } from "./typstHelpers/shared/colors"; -export { generateSubtractionProblemStackFunction } from "./typstHelpers/subtraction/problemStack"; +} from './typstHelpers/shared/types' +export { generateTypstHelpers } from './typstHelpers/shared/helpers' +export { generatePlaceValueColors } from './typstHelpers/shared/colors' +export { generateSubtractionProblemStackFunction } from './typstHelpers/subtraction/problemStack' /** * Generate Typst function for rendering problem stack/grid @@ -24,23 +24,20 @@ export { generateSubtractionProblemStackFunction } from "./typstHelpers/subtract * @param cellSize Size of each digit cell in inches * @param maxDigits Maximum number of digits in any problem on this page (1-6) */ -export function generateProblemStackFunction( - cellSize: number, - maxDigits: number = 3, -): string { - const cellSizeIn = `${cellSize}in`; - const cellSizePt = cellSize * 72; +export function generateProblemStackFunction(cellSize: number, maxDigits: number = 3): string { + const cellSizeIn = `${cellSize}in` + const cellSizePt = cellSize * 72 // Generate place value color assignments (unique color per place value) // Index 0 = ones, 1 = tens, 2 = hundreds, 3 = thousands, 4 = ten-thousands, 5 = hundred-thousands const placeColors = [ - "color-ones", // 0: ones (light blue) - "color-tens", // 1: tens (light green) - "color-hundreds", // 2: hundreds (light yellow) - "color-thousands", // 3: thousands (light pink/rose) - "color-ten-thousands", // 4: ten-thousands (light purple/lavender) - "color-hundred-thousands", // 5: hundred-thousands (light peach/orange) - ]; + 'color-ones', // 0: ones (light blue) + 'color-tens', // 1: tens (light green) + 'color-hundreds', // 2: hundreds (light yellow) + 'color-thousands', // 3: thousands (light pink/rose) + 'color-ten-thousands', // 4: ten-thousands (light purple/lavender) + 'color-hundred-thousands', // 5: hundred-thousands (light peach/orange) + ] return String.raw` // Problem rendering function for addition worksheets (supports 1-${maxDigits} digit problems) @@ -48,7 +45,7 @@ export function generateProblemStackFunction( // Per-problem display flags: show-carries, show-answers, show-colors, show-ten-frames, show-numbers #let problem-stack(a, b, index-or-none, show-carries, show-answers, show-colors, show-ten-frames, show-numbers) = { // Place value colors array for dynamic lookup (index 0 = ones, 1 = tens, ...) - let place-colors = (${placeColors.join(", ")}) + let place-colors = (${placeColors.join(', ')}) // Extract digits dynamically based on problem size let max-digits = ${maxDigits} @@ -203,7 +200,7 @@ export function generateProblemStackFunction( [], // Empty cell for + sign column // Show ten-frames for any place value that needs regrouping ..for i in range(0, actual-digits).rev() { - let shows-frame = show-ten-frames-for-all or (i in regrouping-places) + let shows-frame = show-ten-frames-for-all or regrouping-places.contains(i) if shows-frame { // Show ten-frame for this place value // Top frame: carry destination (next higher place value) @@ -246,7 +243,7 @@ export function generateProblemStackFunction( ) ) } -`; +` } /** @@ -274,10 +271,10 @@ export function generateProblemTypst( addend2: number, cellSize: number, options: DisplayOptions, - problemNumber?: number, + problemNumber?: number ): string { - const cellSizeIn = `${cellSize}in`; - const cellSizePt = cellSize * 72; + const cellSizeIn = `${cellSize}in` + const cellSizePt = cellSize * 72 return String.raw` #let a = ${addend1} @@ -299,7 +296,7 @@ export function generateProblemTypst( #text(size: ${(cellSizePt * 0.6).toFixed(1)}pt, weight: "bold", font: "New Computer Modern Math")[\\#${problemNumber}.] ] ],` - : "" + : '' } grid( columns: (0.5em, ${cellSizeIn}, ${cellSizeIn}, ${cellSizeIn}), @@ -310,41 +307,31 @@ export function generateProblemTypst( ${ options.showCarryBoxes ? options.showPlaceValueColors - ? "diagonal-split-box(" + - cellSizeIn + - ", color-tens, color-hundreds)," - : "box(width: " + - cellSizeIn + - ", height: " + - cellSizeIn + - ", stroke: 0.5pt)[]," - : "v(" + cellSizeIn + ")," + ? 'diagonal-split-box(' + cellSizeIn + ', color-tens, color-hundreds),' + : 'box(width: ' + cellSizeIn + ', height: ' + cellSizeIn + ', stroke: 0.5pt)[],' + : 'v(' + cellSizeIn + '),' } // Tens carry box: shows carry FROM ones (blue) TO tens (green) ${ options.showCarryBoxes ? options.showPlaceValueColors - ? "diagonal-split-box(" + cellSizeIn + ", color-ones, color-tens)," - : "box(width: " + - cellSizeIn + - ", height: " + - cellSizeIn + - ", stroke: 0.5pt)[]," - : "v(" + cellSizeIn + ")," + ? 'diagonal-split-box(' + cellSizeIn + ', color-ones, color-tens),' + : 'box(width: ' + cellSizeIn + ', height: ' + cellSizeIn + ', stroke: 0.5pt)[],' + : 'v(' + cellSizeIn + '),' } [], // First addend [], - box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: ${options.showPlaceValueColors ? "color-hundreds" : "color-none"})[#align(center + horizon)[#if aH > 0 [#aH] else [#h(0pt)]]], - box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: ${options.showPlaceValueColors ? "color-tens" : "color-none"})[#align(center + horizon)[#aT]], - box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: ${options.showPlaceValueColors ? "color-ones" : "color-none"})[#align(center + horizon)[#aO]], + box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: ${options.showPlaceValueColors ? 'color-hundreds' : 'color-none'})[#align(center + horizon)[#if aH > 0 [#aH] else [#h(0pt)]]], + box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: ${options.showPlaceValueColors ? 'color-tens' : 'color-none'})[#align(center + horizon)[#aT]], + box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: ${options.showPlaceValueColors ? 'color-ones' : 'color-none'})[#align(center + horizon)[#aO]], // Second addend with + sign [+], - box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: ${options.showPlaceValueColors ? "color-hundreds" : "color-none"})[#align(center + horizon)[#if bH > 0 [#bH] else [#h(0pt)]]], - box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: ${options.showPlaceValueColors ? "color-tens" : "color-none"})[#align(center + horizon)[#bT]], - box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: ${options.showPlaceValueColors ? "color-ones" : "color-none"})[#align(center + horizon)[#bO]], + box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: ${options.showPlaceValueColors ? 'color-hundreds' : 'color-none'})[#align(center + horizon)[#if bH > 0 [#bH] else [#h(0pt)]]], + box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: ${options.showPlaceValueColors ? 'color-tens' : 'color-none'})[#align(center + horizon)[#bT]], + box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: ${options.showPlaceValueColors ? 'color-ones' : 'color-none'})[#align(center + horizon)[#bO]], // Horizontal line [], @@ -359,7 +346,7 @@ export function generateProblemTypst( box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: color-none, stroke: grid-stroke, inset: 0pt)[], box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: color-none, stroke: grid-stroke, inset: 0pt)[], box(width: ${cellSizeIn}, height: ${cellSizeIn}, fill: color-none, stroke: grid-stroke, inset: 0pt)[],` - : "" + : '' } )${ options.showTenFrames || options.showTenFramesForAll @@ -368,8 +355,8 @@ export function generateProblemTypst( box(inset: 2pt)[ #ten-frames-stacked(${cellSizeIn}, color-ones, color-tens) ]` - : "" + : '' } ) -`; +` } diff --git a/apps/web/src/app/create/worksheets/addition/typstHelpers/subtraction/answerRow.ts b/apps/web/src/app/create/worksheets/addition/typstHelpers/subtraction/answerRow.ts index 6f688fcb..73fd7b71 100644 --- a/apps/web/src/app/create/worksheets/addition/typstHelpers/subtraction/answerRow.ts +++ b/apps/web/src/app/create/worksheets/addition/typstHelpers/subtraction/answerRow.ts @@ -1,8 +1,8 @@ // Answer row and ten-frames rendering for subtraction problems // Shows answer boxes and optional borrowing visualization -import type { CellDimensions } from "../shared/types"; -import { TYPST_CONSTANTS } from "../shared/types"; +import type { CellDimensions } from '../shared/types' +import { TYPST_CONSTANTS } from '../shared/types' /** * Generate Typst code for the line row (separates problem from answer) @@ -11,7 +11,7 @@ import { TYPST_CONSTANTS } from "../shared/types"; * @returns Typst code for line row */ export function generateLineRow(cellDimensions: CellDimensions): string { - const { cellSizeIn } = cellDimensions; + const { cellSizeIn } = cellDimensions return String.raw` // Line row @@ -19,7 +19,7 @@ export function generateLineRow(cellDimensions: CellDimensions): string { ..for i in range(0, grid-digits) { (line(length: ${cellSizeIn}, stroke: heavy-stroke),) }, -`; +` } /** @@ -32,7 +32,7 @@ export function generateLineRow(cellDimensions: CellDimensions): string { * @returns Typst code for ten-frames row */ export function generateTenFramesRow(cellDimensions: CellDimensions): string { - const { cellSizeIn } = cellDimensions; + const { cellSizeIn } = cellDimensions return String.raw` // Ten-frames row (show borrowing visualization) @@ -49,7 +49,7 @@ export function generateTenFramesRow(cellDimensions: CellDimensions): string { ( [], // Empty cell for operator column ..for i in range(0, grid-digits).rev() { - let shows-frame = show-ten-frames-for-all or (i in borrow-places) + let shows-frame = show-ten-frames-for-all or borrow-places.contains(i) if shows-frame { // Show borrowed amount visualization @@ -77,7 +77,7 @@ export function generateTenFramesRow(cellDimensions: CellDimensions): string { } else { () }, -`; +` } /** @@ -90,7 +90,7 @@ export function generateTenFramesRow(cellDimensions: CellDimensions): string { * @returns Typst code for answer boxes row */ export function generateAnswerBoxesRow(cellDimensions: CellDimensions): string { - const { cellSizeIn } = cellDimensions; + const { cellSizeIn } = cellDimensions return String.raw` // Answer boxes (only for actual difference digits, hiding leading zeros) @@ -111,5 +111,5 @@ export function generateAnswerBoxesRow(cellDimensions: CellDimensions): string { ],) } }, -`; +` }