enhance(actions): replace ansi_up with first-party code (#38619)

Replaces the `ansi_up` dependency with first-party code and fixes a
number of bugs in turn.

- Faster rendering, around 7x for plain lines and 3x for colored ones.
- Render many SGR features like hyperlinks, blink, inverse, conceal,
strikethrough, overline, underline styles and underline color, including
`:` sub-parameters, which no longer swallow the codes after them.
- Drop OSC, DCS, SOS, PM and APC with their payload, ending them at BEL,
`ESC \` or the 8-bit ST. A truncated sequence is dropped instead of
corrupting a later line.
- A backspace moves the cursor back a column, so what follows overwrites
it, even across a style change.
- A style inside an OSC 8 label renders instead of leaking, and a
private CSI ending in `m` no longer resets the style.
- Log lines render as DOM nodes, never as markup, and only an `http(s)`
url becomes a link.
- Named colors render as CSS classes, only 24-bit color stays inline.
- Invisible text is now selectable, and the `z-index` workaround is
gone.

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
silverwind
2026-08-05 23:59:26 +02:00
committed by GitHub
parent 42e0c9eca4
commit 74804df4a5
11 changed files with 419 additions and 105 deletions
+7 -5
View File
@@ -4,11 +4,13 @@ export const urlRawRegex = () => /\bhttps?:\/\/[^\s<>[\]]+/gi; // JS regexp has
/** Strip trailing punctuation that is likely not part of the URL. */
export function trimUrlPunctuation(url: string): string {
url = url.replace(/[.,;:'"]+$/, '');
// Strip trailing closing parens only if unbalanced (not part of the URL like Wikipedia links)
while (url.endsWith(')') && (url.match(/\(/g) || []).length < (url.match(/\)/g) || []).length) {
url = url.slice(0, -1);
}
return url;
// Strip trailing closing parens only if unbalanced (not part of the URL like Wikipedia links),
// counted once as a URL can carry as many parens as the text it was found in is long
let unbalanced = 0;
for (const char of url) unbalanced += char === ')' ? 1 : char === '(' ? -1 : 0;
let strip = 0;
while (strip < unbalanced && url[url.length - 1 - strip] === ')') strip++;
return strip ? url.slice(0, -strip) : url;
}
export function urlQueryEscape(s: string) {