fix: interpolation bold doubling and error recovery display fixes#115
Open
fix: interpolation bold doubling and error recovery display fixes#115
Conversation
…iagnostic code - Add exported ErrPartialEvaluation sentinel error for partial evaluation detection - Add unexported diagCodeCascadingError constant for cascading error diagnostics - Add errors import to evaluator.go Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add erroredVars map[string]error field to Environment struct - Add SetError, GetError, ClearError, ClearErrors methods - Initialize erroredVars in NewEnvironment and Clone - Clone copies erroredVars independently using maps.Copy - Add 7 test scenarios covering happy paths, coexistence, and clone isolation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ifier check - Add CascadingError type in errors.go with VarName, Cause, Unwrap() - Modify evalIdentifier to check env.GetError() before env.Get() - Errored variables produce CascadingError instead of returning stale values - Tests: cascading error type, errors.As, precedence over values, binary op propagation, undefined not cascading Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Change the statement evaluation loop from break-on-error to continue-on-error: - Failed statements get nil placeholders maintaining 1:1 results/statements alignment - Cascading errors (from errored variable refs) get hint severity diagnostics - Root-cause errors get error severity diagnostics with eval_error code - Errored assignment variables are tracked via env.SetError() for downstream detection - Block stays dirty when any statement fails; SetLastValue uses last non-nil result - First error preserved in block.SetError() for legacy compatibility Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…EvaluateAffectedBlocks All three evaluation entry points now continue past block errors, collecting diagnostics across the entire document. Returns ErrPartialEvaluation when any block had errors, nil otherwise. - Evaluate(): tracks hasErrors, continues to next block on error - EvaluateBlock() pass 1: parse/redefinition errors become non-fatal - EvaluateBlock() pass 2: evaluateCalcBlockSelective gets statement-level recovery parallel to evaluateCalcBlockWithDoc (Unit 3) - EvaluateAffectedBlocks(): continues past block errors - Semantic checker receives errored variables so downstream blocks get CascadingError instead of undefined_variable - Environment.GetAllErroredVars() added for checker population - CLI eval.go handles ErrPartialEvaluation: formats output then exits 1 - convert.go handles ErrPartialEvaluation: returns partial output + error - Downstream test updates for new error recovery behavior - Golden test file updated for embedded block error formatting Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update all 3 Evaluate() call sites in doceval to handle partial evaluation gracefully instead of treating it as fatal: - generateFullDoc: log warning, continue with partial results - evalProgressive: continue with partial line results - evalBlockIndependent: return BlockResult with partial error and lines Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 3 golden .cm files exercising multi-block error recovery, cascading errors, and mixed success/error scenarios. Add 3 integration tests validating the full evaluator pipeline: - Multi-block: errored block, cascading block, independent block - Cascading: root cause + 2 cascading within block + cross-block - Mixed: div-by-zero mid-document with 4 successful + 4 errored vars
In evalAssignment, call env.ClearError after a successful Set to prevent a variable that was previously errored from appearing as a CascadingError when referenced later — even though it now has a valid value. Found during reliability review.
- Only mark the conflicting variable as errored on redefinition, not all variables in the block (P1 correctness finding) - Track non-recoverable blocks (parse/redefinition) separately so Pass 2 retries runtime-errored blocks with the reactive env, preserving forward-reference reactive semantics (P1 correctness)
- GetAllVariables() now returns a snapshot copy instead of the live map, preventing concurrent map read/write panics if callers hold the reference across evaluation cycles - Statement eval loops now append nil placeholder for zero-result statements (e.g., directives), maintaining 1:1 alignment between results slice and AST nodes. Prevents the statement index drift class of bugs when directives are interspersed with calculations.
Verifies the TUI correctly distinguishes root-cause errors (blocked=false) from cascading errors (blocked=true) using the data-driven catwalk framework. Tests that: - Division by zero shows as eval_error, not blocked - Successful statements after errors show their values - Cascading references show as cascading_error with IsBlocked=true
The Hugo render hook previously treated errors and results as mutually exclusive -- if a block had an error, only the error was shown and all results were hidden. With error recovery producing blocks that have both partial results AND errors: - Add LineResult.Error field to doceval so per-line errors are included in cm_results.json alongside successful results - Update render-codeblock-calcmark.html to show a unified results table with successful values and inline error indicators - Add CSS for .cm-partial-error and .cm-error-value styling - Fatal errors (no results at all) still show the error-only view
The HTML formatter now shows errors inline next to each source line instead of a single block-level error at the bottom: - Root-cause errors: red "✗ division by zero" inline - Cascading errors: amber italic "⚠ depends on errored variable" - Successful lines: blue "= value" as before Adds Error and IsCascading fields to TemplateLine, populates from block diagnostics by line number. Updates both default.gohtml and preview.gohtml templates.
When a calc block contains blank lines between statements, the diagnostic Line number counts all source lines (including blanks), but the HTML formatter and doceval only counted non-blank lines. This caused errors after blank lines to silently show nothing. Test: TestHTMLFormatter_ErrorAfterBlankLine proves the bug with "b = \$23\n\na = 1 / 0" — the error on line 3 was not matched because the counter only reached 2. Fix: count every source line.
Long error messages like "cannot reassign 'a' — variables are immutable" were pushing content sideways when displayed inline to the right of the source. Now errors appear as a compact diagnostic line below the source, keeping the layout clean. Applies to both default.gohtml and preview.gohtml templates. The Hugo render hook (table-based) is unaffected.
When a semantic error (like variable redefinition) aborts a block before interpretation, only the offending line gets a per-line diagnostic. Other lines in the block show nothing — no result, no error. Restore the block-level error div as a fallback so users always see that the block failed, even for lines without per-line diagnostics. Test: TestHTMLFormatter_SemanticErrorShowsOnCorrectLine proves the bug (semantic error diagnostic missing from HTML output) then verifies the fix.
…xist Add HasLineDiagnostic field to TemplateBlock. Templates only show the block-level "Error:" div when no per-line diagnostics were rendered, preventing the same error from appearing twice (once inline, once at the bottom). Text and markdown formatters retain the block-level error as-is — they don't have per-line diagnostic rendering, so the block-level error is their only error indicator.
The evaluator's semantic error handling returned on the first error-severity diagnostic, missing subsequent errors like a second variable redefinition in the same block. Now collects ALL semantic error diagnostics before returning, so every redefinition or type error is visible. Both evaluateCalcBlockWithDoc and evaluateCalcBlockSelective are fixed. Time complexity unchanged: O(n) for diagnostics, O(n) once for variable-error marking. Test: TestMultipleSemanticErrors proves that "a=1/0; a=2; c=3; c=5" reports redefinition errors for both 'a' (line 2) and 'c' (line 4).
BenchmarkEvaluate_ValidDocument: 100-statement chain, ~167µs BenchmarkEvaluate_WithErrors: 50 success + 50 cascading, ~154µs Both well under the 15ms budget. Establishes a baseline for detecting performance regressions from error recovery changes.
Interpolated values were wrapped in **bold** markers, causing
doubled markers (****value****) when users wrote **{{ var }}** in
their markdown. The user controls formatting in their source —
interpolation should just replace the tag with the value.
Test: TestInterpolateLine_BoldSourceDoesNotDouble proves the bug
with "We leave on **{{ out }}**" producing ****42****.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up fixes discovered during Lark playground testing of #112:
{{var}}interpolation wrapped values in**bold**, causing****value****when users wrote**{{ var }}**in their markdown. Removed auto-bold — users control formatting in their sourceTest plan
task test— 31 packages passtask quality— all checks passCo-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com