| author | |
| committer | |
| log | 8bc9b78f827072a89707f6e4b577710e27263697 |
| tree | 94fded5f10f0152d6e5584bdc8dfa13b3736ae20 |
| parent | a21b42cec478b093cdc50cc2105b5368ea8b3546 |
| signature | Signed by PGP key B5690EEEBB952194 |
2 files changed, 34 insertions(+), 4 deletions(-)
apps/web/src/terminal-links.test.ts+25| ... | @@ -97,6 +97,24 @@ describe("extractTerminalLinks", () => { | ... | @@ -97,6 +97,24 @@ describe("extractTerminalLinks", () => { |
| 97 | }, | 97 | }, |
| 98 | ]); | 98 | ]); |
| 99 | }); | 99 | }); |
| 100 | |||
| 101 | it("keeps a trailing colon on URLs", () => { | ||
| 102 | expect(extractTerminalLinks("GET https://example.test/items/foo:")).toEqual([ | ||
| 103 | { kind: "url", text: "https://example.test/items/foo:", start: 4, end: 35 }, | ||
| 104 | ]); | ||
| 105 | }); | ||
| 106 | |||
| 107 | it.each([ | ||
| 108 | ["./main.go:10:5: undefined: x", "./main.go:10:5"], | ||
| 109 | ["/home/dev/app/src/main.c:10:5: error: expected ';'", "/home/dev/app/src/main.c:10:5"], | ||
| 110 | ["C:\\dev\\app\\src\\main.c:10:5: error: expected ';'", "C:\\dev\\app\\src\\main.c:10:5"], | ||
| 111 | ["wrote ./out/report.txt:", "./out/report.txt"], | ||
| 112 | ])("drops the colon that ends a compiler diagnostic location in %s", (line, text) => { | ||
| 113 | const start = line.indexOf(text); | ||
| 114 | expect(extractTerminalLinks(line)).toEqual([ | ||
| 115 | { kind: "path", text, start, end: start + text.length }, | ||
| 116 | ]); | ||
| 117 | }); | ||
| 100 | }); | 118 | }); |
| 101 | 119 | ||
| 102 | describe("collectWrappedTerminalLinkLine", () => { | 120 | describe("collectWrappedTerminalLinkLine", () => { |
| ... | @@ -173,6 +191,13 @@ describe("resolvePathLinkTarget", () => { | ... | @@ -173,6 +191,13 @@ describe("resolvePathLinkTarget", () => { |
| 173 | resolvePathLinkTarget("C:/Users/julius/project/src/main.ts:12", "C:\\Users\\julius\\project"), | 191 | resolvePathLinkTarget("C:/Users/julius/project/src/main.ts:12", "C:\\Users\\julius\\project"), |
| 174 | ).toBe("C:/Users/julius/project/src/main.ts:12"); | 192 | ).toBe("C:/Users/julius/project/src/main.ts:12"); |
| 175 | }); | 193 | }); |
| 194 | |||
| 195 | it("keeps the line and column of a compiler diagnostic", () => { | ||
| 196 | const [link] = extractTerminalLinks("/Users/julius/project/main.c:10:5: error: expected ';'"); | ||
| 197 | expect(resolvePathLinkTarget(link?.text ?? "", "/Users/julius/project")).toBe( | ||
| 198 | "/Users/julius/project/main.c:10:5", | ||
| 199 | ); | ||
| 200 | }); | ||
| 176 | }); | 201 | }); |
| 177 | 202 | ||
| 178 | describe("isTerminalLinkActivation", () => { | 203 | describe("isTerminalLinkActivation", () => { |
apps/web/src/terminal-links.ts+9-4| ... | @@ -35,9 +35,14 @@ const URL_PATTERN = /https?:\/\/[^\s"'`<>]+/giu; | ... | @@ -35,9 +35,14 @@ const URL_PATTERN = /https?:\/\/[^\s"'`<>]+/giu; |
| 35 | const FILE_PATH_PATTERN = | 35 | const FILE_PATH_PATTERN = |
| 36 | /(?:~\/|\.{1,2}\/|\/|[A-Za-z]:[\\/]|\\\\)[^\s"'`<>]+|[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)+(?::\d+){0,2}/g; | 36 | /(?:~\/|\.{1,2}\/|\/|[A-Za-z]:[\\/]|\\\\)[^\s"'`<>]+|[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)+(?::\d+){0,2}/g; |
| 37 | const TRAILING_PUNCTUATION_PATTERN = /[.,;!?]+$/; | 37 | const TRAILING_PUNCTUATION_PATTERN = /[.,;!?]+$/; |
| 38 | 38 | // Paths also drop a trailing colon: compilers end `file:line:col:` with one. | |
| 39 | function trimClosingDelimiters(value: string): string { | 39 | const TRAILING_PATH_PUNCTUATION_PATTERN = /[.,;:!?]+$/; |
| 40 | let output = value.replace(TRAILING_PUNCTUATION_PATTERN, ""); | 40 | |
| 41 | function trimClosingDelimiters(value: string, kind: TerminalLinkKind): string { | ||
| 42 | let output = value.replace( | ||
| 43 | kind === "path" ? TRAILING_PATH_PUNCTUATION_PATTERN : TRAILING_PUNCTUATION_PATTERN, | ||
| 44 | "", | ||
| 45 | ); | ||
| 41 | if (output.length === 0) return output; | 46 | if (output.length === 0) return output; |
| 42 | 47 | ||
| 43 | const trimUnbalanced = (open: string, close: string) => { | 48 | const trimUnbalanced = (open: string, close: string) => { |
| ... | @@ -73,7 +78,7 @@ function collectMatches( | ... | @@ -73,7 +78,7 @@ function collectMatches( |
| 73 | const start = rawMatch.index ?? -1; | 78 | const start = rawMatch.index ?? -1; |
| 74 | if (start < 0 || raw.length === 0) continue; | 79 | if (start < 0 || raw.length === 0) continue; |
| 75 | 80 | ||
| 76 | const trimmed = trimClosingDelimiters(raw); | 81 | const trimmed = trimClosingDelimiters(raw, kind); |
| 77 | if (trimmed.length === 0) continue; | 82 | if (trimmed.length === 0) continue; |
| 78 | if (kind === "path" && isTerminalUrl(trimmed)) continue; | 83 | if (kind === "path" && isTerminalUrl(trimmed)) continue; |
| 79 | 84 |