feat: transient variables — reactive but excluded from persistence (#137)#138
Merged
Conversation
|
Release preview: merging this PR will publish v0.43.0 (minor bump from v0.42.0) |
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- render.tsx: getVariableTextValue resolves transient scope for markdown - interpolation.ts: INTERP_TEST, resolveSimple, interpolate, and interpolateExpression all handle % sigil and transient namespace - VarDisplay.tsx already handled by Task 4 (no changes needed) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5de3656 to
c8f3db9
Compare
4 tasks
rohal12
added a commit
that referenced
this pull request
Mar 27, 2026
…143) (#144) ## Summary - **Performance fix for issue #143**: Extend the `renderNodes` fast path to skip the micromark + innerHTML pipeline when all text nodes contain only whitespace (indentation, newlines between HTML tags) - Eliminates ~97 redundant pipeline calls per render in `{for}` loops over HTML + macro content, addressing 89% of wall time in Chrome CPU profiles - Preserves blank-line (`\n\n`) detection to maintain paragraph separation semantics ## Also includes (prior work on this branch) - Published types sync (#135) - Mutation buffer (#136) - Transient variables (#137, #138) - Computed @-target in for-loops (#140) ## Test plan - [x] 3 new correctness baseline tests for the fast path - [x] Full test suite passes (1090 tests) - [x] Type check clean (`tsc --noEmit`) - [ ] Manual verification: re-profile the 23-item for-loop passage in Chrome to confirm wall time reduction 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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
%variable scope (transient): reactive Zustand-backed variables excluded from all persistence (history snapshots, save payloads, session storage). Declared in an optionalStoryTransientspassage with%name = valuesyntax.{%var}display,{set %var = expr},{unset %var}, conditionals, loops, expressions, andStory.set('%var', val)/Story.get('%var')API withvariableChangedevents using%-prefixed keys.storeVarrejection for input macros, and transient propagation through allevaluate()callsites (ExprDisplay, Computed, triggers, WidgetInvocation).Closes #137
Changes (27 files, +557 −59)
expression.tsTRANS_REregex with(?<!\w)lookbehind for modulo disambiguation,transientparameter onevaluate()/execute()store.tstransient/transientDefaultsstate,setTransient/deleteTransientactions, init/restart/load integrationstory-variables.ts,index.tsxparseStoryVariableswith sigil,StoryTransientspassage parsing, cross-scope collision checktokenizer.ts,ast.ts%sigil in bare and CSS-selector-prefixed variable pathsVarDisplay.tsx,render.tsx,interpolation.tstransientscope in display, markdown integration, string interpolationuse-merged-locals.ts,use-interpolate.tsdefine-macro.ts,execute-mutation.ts,Unset.tsxmergedflag, mutation diffing,{unset %var}routingdefine-macro.tsstoreVarrejects%sigil for input macrosstory-api.ts%sigil routing inget()/set(),variableChangedevent with%prefixExprDisplay.tsx,Computed.tsx,triggers.ts,WidgetInvocation.tsxtransientto allevaluate()callsitestypes/index.d.ts%prefix onget()/set()variables.md,special-passages.md,story-api.md,markup.md,CHANGELOG.mdexpression.test.ts,transient-variables.test.tsxTest plan
npx tsc --noEmit— cleannpx vitest run— 1068 tests pass (1 pre-existing build integration skip)%transform, modulo disambiguation, string literal preservation, mixed sigils{%var}display,{set},{unset},{if},{for}, navigation persistence, goBack stays current, save exclusion, restart reset🤖 Generated with Claude Code