fix(process): treat non-ASCII letters as port continuations

\w is ASCII-only even with the u flag, so "port: 8080.β" was treated as
a sentence-ending port. Use Unicode letter and number classes for the
port boundary checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kaoru0822andClaude Opus 5.5 committed 2026-10-09 14:28:19 +00:00
1 parent 184ed970b9
commit ad813e473b
2 files changed
+7 -4

No files matched your search

@@ -106,6 +106,7 @@ it("normalizes ports that end a sentence but not decimal or host continuations",
"Bound [::1]:3000.",
"listen=9000.\n",
"port: 80.5 localhost:8080.5 localhost:8080.example.test",
"port: 8080.β localhost:8080.é port: 8080é",
].join("\n");
expect(normalizeProcessText(input, scenario({}), "/temporary", rootPid)).toBe(
[
@@ -114,6 +115,7 @@ it("normalizes ports that end a sentence but not decimal or host continuations",
"Bound [::1]:<port>.",
"listen=<port>.\n",
"port: 80.5 localhost:8080.5 localhost:8080.example.test",
"port: 8080.β localhost:8080.é port: 8080é",
].join("\n"),
);
});
+5 -4
View File
@@ -41,13 +41,14 @@ export const normalizeProcessText = (
return normalized;
};
// A port may end a sentence, but a period followed by a word character
// continues a decimal, version, or host name and is not a port boundary.
// A port may end a sentence, but a period followed by a letter, digit, or
// underscore in any script continues a decimal, version, or host name and is
// not a port boundary.
// PTY chunks are normalized independently, so a period that ends the chunk
// stays unnormalized: its continuation may arrive in the next chunk.
const normalizePortTokens = (value: string): string => {
const endpointNormalized = value.replaceAll(
/(\b[a-z][a-z0-9+.-]*:\/\/[^\s/?#"'<>]+|\blocalhost|\b(?:\d{1,3}\.){3}\d{1,3}|\[[\da-f:.%]+\]):(\d{1,5})(?![\w@:]|\.(?:\w|$))/giu,
/(\b[a-z][a-z0-9+.-]*:\/\/[^\s/?#"'<>]+|\blocalhost|\b(?:\d{1,3}\.){3}\d{1,3}|\[[\da-f:.%]+\]):(\d{1,5})(?![\p{L}\p{N}_@:]|\.(?:[\p{L}\p{N}_]|$))/giu,
(match: string, endpoint: string, port: string) => {
if (Number(port) > 65_535) return match;
const isEndpoint = endpoint.includes("://")
@@ -58,7 +59,7 @@ const normalizePortTokens = (value: string): string => {
},
);
return endpointNormalized.replaceAll(
/(\b(?:port|tcp_port|udp_port|listen)\b["']?\s*[:=]\s*)(\d{1,5})(?!\w|\.(?:\w|$))/giu,
/(\b(?:port|tcp_port|udp_port|listen)\b["']?\s*[:=]\s*)(\d{1,5})(?![\p{L}\p{N}_]|\.(?:[\p{L}\p{N}_]|$))/giu,
(match: string, prefix: string, port: string) =>
Number(port) <= 65_535 ? `${prefix}<port>` : match,
);