Story
As an Executable Markdown author, I want to render an arbitrary string as a fenced Markdown code block without that string being able to close the fence, so generated source and diagnostics can be presented safely without eval.
<CodeBlock value={source} language="markdown" />
Contract
<CodeBlock> is a generic first-party text component.
- It is self-closing and requires a string
value.
language is optional. When present, it is non-empty and matches ^[A-Za-z0-9][A-Za-z0-9._+#-]*$. This admits common single-token language identifiers such as markdown, shell-session, c++, and c#, while excluding whitespace, backticks, and Markdown extension syntax outside that closed alphabet.
- A backtick run is a contiguous sequence of U+0060 characters in
value. The component chooses the shortest safe fence: max(3, longest backtick run + 1) backticks.
- The rendered string is exactly
fence + (language ?? "") + "\n" + value + "\n" + fence. The two U+000A line feeds frame the value and are not part of it. The component adds no line feed after the closing fence.
- The value's characters appear unchanged between the framing line feeds. It is not escaped, parsed, evaluated, normalized, or rewritten.
- Exactness is defined at the component rendering and
as capture boundary. Ordinary DocumentOutput middleware remains free to transform emitted document output under its existing contract; a caller requiring terminal byte preservation uses xmd run --raw.
- It performs no durable effect and uses ordinary text rendering and
as capture semantics. Capturing with as receives the exact rendered string above and emits nothing at the invocation site.
- It is an ordinary overridable core default. A repository
CodeBlock.md is selected ahead of it under normal component resolution.
- Content, a missing value, a non-string value, and an invalid language token are refused before rendering.
- A candidate containing fences, component syntax, interpolation, HTML, or executable blocks remains inert text.
Suggested syntax description:
Show arbitrary text as a fenced Markdown code block. <CodeBlock value={source} language="markdown" /> chooses a fence the value cannot close.
Motivation
Issue #260 needs to show the exact generated document and structured validation diagnostics inside an <Elicit> message. Computing a delimiter in an eval block would move generic presentation machinery into authored JavaScript and would give the planning document authority it does not need.
Acceptance
- Empty text and ordinary Markdown render as one valid fenced block using the shortest safe fence.
- A value containing backtick runs longer than three receives a fence exactly one character longer than its longest run and cannot close it.
- Removing the opening delimiter and its framing line feed, and the closing delimiter and its framing line feed, recovers the exact input string, including leading and trailing whitespace and repeated blank lines.
- An omitted language produces no info string.
language="md", language="json", language="shell-session", language="c++", and language="c#" produce those exact tokens.
- Empty language, whitespace, backticks, and characters outside the closed language alphabet are refused.
- Invalid shape or props render nothing and perform no component effect.
- Capturing with
as returns the exact fenced Markdown the raw uncaptured component rendering produces. Normalized host output and --raw behavior retain their existing contracts.
- The component has no component-specific durable event. A partial replay renders from the reconstructed value, and completed-root reuse does not invoke it.
- A repository
CodeBlock.md overrides the core default; otherwise inspection reports the ordinary @executablemd/core registration with self-closing form, the closed props schema, text return mode, and ordinary optional as behavior.
- The component is documented in the syntax catalog and covered under Deno, Node and Bun through the shared corpus.
Relationship
This is a prerequisite for #260. It is presentation only: it does not admit or execute the supplied text.
Story
As an Executable Markdown author, I want to render an arbitrary string as a fenced Markdown code block without that string being able to close the fence, so generated source and diagnostics can be presented safely without eval.
Contract
<CodeBlock>is a generic first-party text component.value.languageis optional. When present, it is non-empty and matches^[A-Za-z0-9][A-Za-z0-9._+#-]*$. This admits common single-token language identifiers such asmarkdown,shell-session,c++, andc#, while excluding whitespace, backticks, and Markdown extension syntax outside that closed alphabet.value. The component chooses the shortest safe fence:max(3, longest backtick run + 1)backticks.fence + (language ?? "") + "\n" + value + "\n" + fence. The two U+000A line feeds frame the value and are not part of it. The component adds no line feed after the closing fence.ascapture boundary. OrdinaryDocumentOutputmiddleware remains free to transform emitted document output under its existing contract; a caller requiring terminal byte preservation usesxmd run --raw.ascapture semantics. Capturing withasreceives the exact rendered string above and emits nothing at the invocation site.CodeBlock.mdis selected ahead of it under normal component resolution.Suggested syntax description:
Motivation
Issue #260 needs to show the exact generated document and structured validation diagnostics inside an
<Elicit>message. Computing a delimiter in an eval block would move generic presentation machinery into authored JavaScript and would give the planning document authority it does not need.Acceptance
language="md",language="json",language="shell-session",language="c++", andlanguage="c#"produce those exact tokens.asreturns the exact fenced Markdown the raw uncaptured component rendering produces. Normalized host output and--rawbehavior retain their existing contracts.CodeBlock.mdoverrides the core default; otherwise inspection reports the ordinary@executablemd/coreregistration with self-closing form, the closed props schema, text return mode, and ordinary optionalasbehavior.Relationship
This is a prerequisite for #260. It is presentation only: it does not admit or execute the supplied text.