Skip to content

Commit f312530

Browse files
Display error messages in the Documentation Live Preview Editor (#1302)
1 parent 75d82a9 commit f312530

File tree

6 files changed

+124
-5
lines changed

6 files changed

+124
-5
lines changed

.vscodeignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,7 @@
88
!dist/**
99
!images/**
1010
!snippets/**
11-
!assets/icon-font.woff
11+
!assets/icons/**
12+
!assets/documentation-webview/**
13+
!assets/swift-docc-render/**
14+
!node_modules/@vscode/codicons/**

package-lock.json

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,6 +1420,7 @@
14201420
"typescript": "^5.7.2"
14211421
},
14221422
"dependencies": {
1423+
"@vscode/codicons": "^0.0.36",
14231424
"lcov-parse": "^1.0.0",
14241425
"plist": "^3.1.0",
14251426
"vscode-languageclient": "^9.0.1",

src/documentation/DocumentationPreviewEditor.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the VS Code Swift open source project
44
//
5-
// Copyright (c) 2024 the VS Code Swift project authors
5+
// Copyright (c) 2024-2025 the VS Code Swift project authors
66
// Licensed under Apache License v2.0
77
//
88
// See LICENSE.txt for license information
@@ -40,6 +40,11 @@ export class DocumentationPreviewEditor implements vscode.Disposable {
4040
{
4141
enableScripts: true,
4242
localResourceRoots: [
43+
vscode.Uri.file(
44+
extension.asAbsolutePath(
45+
path.join("node_modules", "@vscode/codicons", "dist")
46+
)
47+
),
4348
vscode.Uri.file(
4449
extension.asAbsolutePath(path.join("assets", "documentation-webview"))
4550
),
@@ -72,8 +77,16 @@ export class DocumentationPreviewEditor implements vscode.Disposable {
7277
path.join(swiftDoccRenderPath, "index.html"),
7378
"utf-8"
7479
);
80+
const codiconsUri = webviewPanel.webview.asWebviewUri(
81+
vscode.Uri.file(
82+
extension.asAbsolutePath(
83+
path.join("node_modules", "@vscode/codicons", "dist", "codicon.css")
84+
)
85+
)
86+
);
7587
doccRenderHTML = doccRenderHTML
7688
.replaceAll("{{BASE_PATH}}", webviewBaseURI.toString())
89+
.replace("</head>", `<link href="${codiconsUri}" rel="stylesheet" /></head>`)
7790
.replace("</body>", `<script src="${scriptURI.toString()}"></script></body>`);
7891
webviewPanel.webview.html = doccRenderHTML;
7992
return new DocumentationPreviewEditor(context, webviewPanel);
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the VS Code Swift open source project
4+
//
5+
// Copyright (c) 2025 the VS Code Swift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of VS Code Swift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
export class ErrorMessage {
16+
private readonly containerElement: HTMLDivElement;
17+
private readonly iconElement: HTMLSpanElement;
18+
private readonly messageElement: HTMLSpanElement;
19+
20+
constructor() {
21+
this.containerElement = createContainer();
22+
this.iconElement = createIcon();
23+
this.messageElement = createMessage();
24+
this.containerElement.appendChild(this.iconElement);
25+
this.containerElement.appendChild(this.messageElement);
26+
window.document.body.appendChild(this.containerElement);
27+
}
28+
29+
show(message: string) {
30+
this.messageElement.textContent = message;
31+
this.containerElement.style.display = "flex";
32+
}
33+
34+
hide() {
35+
this.containerElement.style.display = "none";
36+
}
37+
}
38+
39+
function createContainer(): HTMLDivElement {
40+
const containerElement = document.createElement("div");
41+
containerElement.style.backgroundColor = "var(--vscode-editor-background)";
42+
containerElement.style.color = "var(--vscode-foreground)";
43+
containerElement.style.fontFamily = "var(--vscode-font-family)";
44+
containerElement.style.fontWeight = "var(--vscode-font-weight)";
45+
containerElement.style.width = "100%";
46+
containerElement.style.height = "100%";
47+
containerElement.style.display = "none";
48+
containerElement.style.gap = "10px";
49+
containerElement.style.flexDirection = "column";
50+
containerElement.style.alignItems = "center";
51+
containerElement.style.justifyContent = "center";
52+
containerElement.style.position = "absolute";
53+
containerElement.style.top = "0";
54+
containerElement.style.left = "0";
55+
return containerElement;
56+
}
57+
58+
function createIcon(): HTMLSpanElement {
59+
const iconElement = document.createElement("span");
60+
iconElement.className = "codicon codicon-error";
61+
iconElement.style.color = "var(--vscode-editorError-foreground)";
62+
iconElement.style.fontSize = "48px";
63+
return iconElement;
64+
}
65+
66+
function createMessage(): HTMLSpanElement {
67+
const messageElement = document.createElement("span");
68+
messageElement.style.fontSize = "14px";
69+
return messageElement;
70+
}

src/documentation/webview/webview.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the VS Code Swift open source project
44
//
5-
// Copyright (c) 2024 the VS Code Swift project authors
5+
// Copyright (c) 2024-2025 the VS Code Swift project authors
66
// Licensed under Apache License v2.0
77
//
88
// See LICENSE.txt for license information
@@ -14,13 +14,15 @@
1414

1515
import { RenderNode, WebviewContent, WebviewMessage } from "./WebviewMessage";
1616
import { createCommunicationBridge } from "./CommunicationBridge";
17+
import { ErrorMessage } from "./ErrorMessage";
1718

1819
createCommunicationBridge().then(async bridge => {
1920
const vscode = acquireVsCodeApi();
2021
let activeDocumentationPath: string | undefined;
2122
let contentToApplyOnRender: RenderNode | undefined;
2223

23-
window.document.getElementById("app");
24+
// An HTML element that displays an error message to the user
25+
const errorMessage = new ErrorMessage();
2426

2527
// Handle messages coming from swift-docc-render
2628
bridge.onDidReceiveMessage(message => {
@@ -53,6 +55,7 @@ createCommunicationBridge().then(async bridge => {
5355
});
5456
function handleUpdateContentMessage(content: WebviewContent) {
5557
if (content.type === "render-node") {
58+
hideErrorMessage();
5659
const renderNode = content.renderNode;
5760
const documentationPath: string = (() => {
5861
switch (renderNode.kind) {
@@ -76,10 +79,27 @@ createCommunicationBridge().then(async bridge => {
7679
bridge.send({ type: "contentUpdate", data: renderNode });
7780
}
7881
} else {
79-
// Show the error message
82+
showErrorMessage(content.errorMessage);
83+
vscode.postMessage({ type: "rendered" });
8084
}
8185
}
8286

87+
function showErrorMessage(message: string) {
88+
const app = window.document.getElementById("app");
89+
if (app) {
90+
app.style.display = "none";
91+
}
92+
errorMessage.show(message);
93+
}
94+
95+
function hideErrorMessage() {
96+
const app = window.document.getElementById("app");
97+
if (app) {
98+
app.style.display = "block";
99+
}
100+
errorMessage.hide();
101+
}
102+
83103
// Notify vscode-swift that we're ready to receive messages
84104
vscode.postMessage({ type: "loaded" });
85105
});

0 commit comments

Comments
 (0)