💥 Namespace Markdown props under the props binding - #372
Conversation
PR #372: 💥 Namespace Markdown props under the
|
| // context env so that ancestor bindings propagate through all levels. | ||
| // The current context env's bindings take precedence (innermost-wins). | ||
| // The current context env's ordinary bindings take precedence; the shared | ||
| // layering helper keeps a projected caller's props object lexical. |
There was a problem hiding this comment.
Redundant comment — restates what the code does.
| // layering helper keeps a projected caller's props object lexical. |
| // the lexical caller's bindings under the current component's, so what | ||
| // it reads is what its author wrote beside it. | ||
| // Projection follows the same ordinary-binding layering as Markdown | ||
| // expansion while retaining the projected caller's props namespace. |
There was a problem hiding this comment.
Redundant comment — restates what the code does.
| // expansion while retaining the projected caller's props namespace. |
| ```ts eval | ||
| // Install Sample Api middleware on the current component scope. | ||
| // baseUrl and model are closed over here — no context lookup at call time. | ||
| // baseUrl and props.model are closed over here — no context lookup at call time. |
There was a problem hiding this comment.
Redundant comment — restates what the code does.
| // baseUrl and props.model are closed over here — no context lookup at call time. |
5d6da5c to
52c714f
Compare
52c714f to
5c927b8
Compare
| // Slots were resolved during substitution, so the environment, meta, | ||
| // props and hide set are the body's own — only the resource scope moves. | ||
| // Slots were resolved during substitution. The projected content keeps | ||
| // the caller frame; only the resource scope moves. |
There was a problem hiding this comment.
Redundant comment — restates what the code does.
| // the caller frame; only the resource scope moves. |
| // context env so that ancestor bindings propagate through all levels. | ||
| // The current context env's bindings take precedence (innermost-wins). | ||
| // The current context env's ordinary bindings take precedence; the shared | ||
| // layering helper keeps a projected caller's props object lexical. |
There was a problem hiding this comment.
Redundant comment — restates what the code does.
| // layering helper keeps a projected caller's props object lexical. |
| // the lexical caller's bindings under the current component's, so what | ||
| // it reads is what its author wrote beside it. | ||
| // Projection follows the same ordinary-binding layering as Markdown | ||
| // expansion while retaining the projected caller's props namespace. |
There was a problem hiding this comment.
Redundant comment — restates what the code does.
| // expansion while retaining the projected caller's props namespace. |
Why
Issue #305 changes Markdown props from implicit bare bindings to an explicit
propsnamespace. Validated props are available consistently across root documents, Markdown components, text interpolation, eval blocks, executable blocks, and projected content.Closes #305.
What changes
BREAKING:
Before:
namecreated both{name}and{props.name}access.After:
env.values.propsobject.props.name, including{props.name}interpolation.nameno longer creates a barenamebinding.props.name.propsfollows normal shadowing and restoration rules in text, eval, and executable interpolation.The exact validated object is installed without another clone or freeze. Projected content keeps the caller's lexical props object; component-authored content uses the component's validated props. Existing ordinary projected-binding lookup is preserved.
How it works
The review and repository-analysis documents also normalize Oxlint data before it reaches the durable stream. Compatibility probes emit aggregate facts, diagnostic payloads retain only fields consumed by
parseDiagnostics, and PR review diagnostics are limited to changed files.Review workflow hardening
.github/workflows/review.ymland.github/workflows/repo-analysis.ymlnow execute the checked-out revision:deno task deps.deno task build../dist/xmd.They keep secret detection enabled. Credentials are created inside non-serializable header factories, and diagnostic data is bounded before persistence. After XMD runs, each workflow fails closed unless the root journal close exists, is successful (including nested output status), and contains no
<!-- ERROR:marker. Journal upload remains underif: always().The review correctness prompt also bounds
diffPreviewto 40,000 characters so large reviews remain within the provider context limit.Review guide
Start with:
packages/core/src/eval-env.ts,packages/core/src/expand.ts, andpackages/core/tests/props-binding.test.tsThen review:
What must stay true
definition.fn(validatedProps)with unchanged generator arguments.xmd workflowlifecycle code remain outside this PR.How to verify it
<!-- ERROR:marker.Scope
Included
Intentionally unchanged
xmd workflowlifecycle code.New dependencies
None.
Generated or mechanical changes
Review components/policies, smoke fixtures, bundled providers, and embedded examples contain mechanical
prop.name→props.namemigrations. No changeset or version bump is required.Risks and limitations
This is an intentional breaking language change; consumers using bare declared props must migrate to
props.name.Verification
Latest pushed head:
5d6da5c.GitHub checks all pass, including
review,lint,jsr,test-deno,test-node,test-bun,smoke,site, anddeploy/taras/executablemd.composabilityis intentionally skipped for this pull request.In a fresh prepared clone:
deno task lint— pass, 0 errors (1,227 existing warnings).deno task check— pass.deno task test— pass, 383 passed and 0 failed.deno task check:jsr— pass,Success Dry run complete.deno task test:bun— pass, 2,487 passed and 0 failed.deno task test:node— one failure inpackages/core/tests/config-api.test.ts, the known asynchronous-teardown issue tracked by 💥 Stabilize Node runtime test flake in config-api CF7 #371; the GitHubtest-nodecheck passes.git diff --check— pass.Scope confirmation