Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions surfaces/gui/src/components/Markdown.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ describe("Markdown artifact links", () => {
expect(screen.getByTestId("artifact-chip").textContent).toContain("report.pdf");
});

it("dispatches a decoded Unicode filename", () => {
const seen: string[] = [];
const listener = (e: Event) => seen.push((e as CustomEvent).detail.path);
window.addEventListener(OPEN_ARTIFACT_EVENT, listener);

render(<Markdown text="[News](artifact:%E6%96%B0%E9%97%BB%E6%91%98%E8%A6%81.md)" />);
fireEvent.click(screen.getByTestId("artifact-chip"));
expect(seen).toEqual(["新闻摘要.md"]);

window.removeEventListener(OPEN_ARTIFACT_EVENT, listener);
});

// Seventeenth pass: the lead's one-time board mention — [Board · 5 items](board:)
// renders as an inline pill that opens the drawer on its Board section.
it("renders a board: link as a pill and dispatches the open-board event", () => {
Expand Down
14 changes: 11 additions & 3 deletions surfaces/gui/src/components/Markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,22 @@ function BoardChip({ label }: { label: string }) {

function ArtifactChip({ path, title }: { path: string; title: string }) {
const { t } = useTranslation();
const file = path.split("/").pop() || path;
let decodedPath = path;
try {
decodedPath = decodeURIComponent(path);
} catch {
// Literal percent signs are valid in filenames even when they are not URL encoding.
}
const file = decodedPath.split(/[\\/]/).pop() || decodedPath;
return (
<button
className="art-chip"
data-testid="artifact-chip"
title={path}
title={decodedPath}
onClick={() =>
window.dispatchEvent(new CustomEvent(OPEN_ARTIFACT_EVENT, { detail: { path } }))
window.dispatchEvent(
new CustomEvent(OPEN_ARTIFACT_EVENT, { detail: { path: decodedPath } }),
)
}
>
<span className="art-chip-ico">
Expand Down