mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
Six findings. Each terminal-semantics case was checked in a real terminal (tmux, reading back the painted screen) before changing anything: `100%\r\x1b[KOK` shows `OK`. Modelling the `\r` without its erase left the previous frame's tail standing — a regression against the old truncate, since `\r\x1b[K` is the single idiom every spinner and progress bar writes. Erase is now part of the same replay, in all three parameter forms. `a\tb\rXY` shows `XY b`. Counting a tab as one column produced `XYb` and destroyed the alignment this card exists to hold, so the cursor now advances by terminal columns: tabs reach the next 8-column stop and a wide character takes two cells. `\x1b[31mabc\rX\nnext` paints BOTH lines red. A newline does not reset the graphic state, so state threads from one replayed line to the next instead of closing at each line end. Only `m` accumulates into a cell's style now. Folding cursor and erase sequences in grew the state string per redraw and emitted boundaries anser had to discard. The empty check reads the parsed lines the card renders rather than the raw text: output that is only escapes or control bytes survives `trim()` yet parses to nothing, and drew blank rows plus a copy control for invisible bytes instead of the placeholder. The gutter is the card's own left padding rather than a margin. Every render site rewrites `margin` wholesale for its own indent, which silently cancelled the reservation and let a container clip the dot. The fixture sample no longer carries an `[exit code: 1]` line: the real bash presenter consumes that marker precisely because the card shows the exit as its own pill, so the built-bundle snapshot had pinned a frame showing it twice — one the product path cannot produce.
147 lines
4.1 KiB
CSS
147 lines
4.1 KiB
CSS
/* Geometry mirrors CodeBlock (12px radius, code-block surface + banner rows,
|
|
markdown code-block font) so a terminal card and a fenced code block read as
|
|
one family. The one deliberate divergence: output keeps `white-space: pre`
|
|
and scrolls horizontally, because folding a column-aligned command's output
|
|
destroys its alignment. */
|
|
|
|
.block {
|
|
--dsl-terminal-radius: 12px;
|
|
--dsl-terminal-line-height: 22px;
|
|
/* The card's own left inset, holding the run-state dot in a column of its own
|
|
so it never competes with the commands for horizontal space. */
|
|
--dsl-terminal-gutter: 30px;
|
|
|
|
position: relative;
|
|
margin: 16px 0;
|
|
/* The gutter is the card's OWN padding, not a margin: every consumer rewrites
|
|
`margin` wholesale (each render site sets its own indent), which silently
|
|
cancelled the reservation and let the dot fall outside the card into a
|
|
container that clips it. Owning the reservation here keeps the invariant
|
|
with the component that depends on it. */
|
|
padding-left: var(--dsl-terminal-gutter);
|
|
color: var(--dsw-alias-label-primary);
|
|
background: var(--dsw-alias-markdown-code-block);
|
|
border-radius: var(--dsl-terminal-radius);
|
|
}
|
|
|
|
/* Top-aligned: the status pill and copy control stay on the first prompt row
|
|
however many command lines the card carries. */
|
|
.header {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 12px;
|
|
/* No left padding: the card's gutter already insets this row, and the banner
|
|
background still has to span the full surface. */
|
|
padding: 9px 14px 9px 0;
|
|
background: var(--dsw-alias-markdown-code-block-banner);
|
|
border-top-left-radius: var(--dsl-terminal-radius);
|
|
border-top-right-radius: var(--dsl-terminal-radius);
|
|
}
|
|
|
|
/* One row per command line. The prompt column is the only element allowed to
|
|
shrink; the status pill and the copy control keep their intrinsic width. */
|
|
.prompt {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-width: 0;
|
|
flex: 1;
|
|
font: var(--dsw-font-markdown-code-block);
|
|
}
|
|
|
|
.promptLine {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 8px;
|
|
min-width: 0;
|
|
line-height: var(--dsl-terminal-line-height);
|
|
}
|
|
|
|
/* Out of flow inside the card's own gutter padding, so the reservation and the
|
|
dot move together and no consumer margin can pull them apart; the dot neither
|
|
indents its command nor depends on the command's text metrics to line up.
|
|
Centered against the row's line box, not the code font's baseline. */
|
|
.runState {
|
|
position: absolute;
|
|
left: calc(-1 * var(--dsl-terminal-gutter) + 8px);
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
}
|
|
|
|
/* The dot is aria-hidden; this is its text label for assistive technology. */
|
|
.runStateLabel {
|
|
position: absolute;
|
|
width: 1px;
|
|
height: 1px;
|
|
overflow: hidden;
|
|
clip-path: inset(50%);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.cwd {
|
|
flex: none;
|
|
color: var(--dsw-alias-label-tertiary);
|
|
}
|
|
|
|
/* `pre`, not `nowrap`: the prompt row renders the command verbatim, and
|
|
`nowrap` collapses the repeated spaces, tabs, and alignment of an indented
|
|
continuation. Both hold the single row and the ellipsis. */
|
|
.command {
|
|
min-width: 0;
|
|
color: var(--dsw-alias-label-primary);
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: pre;
|
|
}
|
|
|
|
.status {
|
|
flex: none;
|
|
color: var(--dsw-alias-state-error-primary);
|
|
}
|
|
|
|
.copyButton {
|
|
flex: none;
|
|
background-color: transparent;
|
|
border: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
color: var(--dsw-alias-label-secondary);
|
|
cursor: pointer;
|
|
font: var(--dsw-font-xs-13);
|
|
}
|
|
|
|
.output {
|
|
padding: 12px 14px 12px 0;
|
|
font: var(--dsw-font-markdown-code-block);
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
}
|
|
|
|
/* No wrapping, no word-break: alignment is the payload of terminal output. */
|
|
.line {
|
|
min-height: var(--dsl-terminal-line-height);
|
|
white-space: pre;
|
|
}
|
|
|
|
.expand {
|
|
display: block;
|
|
width: 100%;
|
|
padding: 0;
|
|
border: none;
|
|
background-color: transparent;
|
|
color: var(--dsw-alias-label-tertiary);
|
|
cursor: pointer;
|
|
font: inherit;
|
|
text-align: left;
|
|
}
|
|
|
|
.expand:hover {
|
|
color: var(--dsw-alias-label-secondary);
|
|
}
|
|
|
|
.empty {
|
|
padding: 12px 14px 12px 0;
|
|
font: var(--dsw-font-markdown-code-block);
|
|
color: var(--dsw-alias-label-tertiary);
|
|
}
|