Skip to content

Commit

Permalink
feat: add welcome/reference webview to vscode extension (#7777)
Browse files Browse the repository at this point in the history
* add webview

* fixup

* changeset

* feedback

* getting started tweaks
  • Loading branch information
emily-shen authored Jan 24, 2025
1 parent 40f89a9 commit 248bdb2
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/dry-pens-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"cloudflare-workers-bindings-extension": patch
---

feat: add home view with getting started information
98 changes: 98 additions & 0 deletions packages/cloudflare-workers-bindings-extension/media/main.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
:root {
--container-paddding: 20px;
--input-padding-vertical: 6px;
--input-padding-horizontal: 4px;
--input-margin-vertical: 6px;
--input-margin-horizontal: 0;
--line-height: 1.4rem;
}

body {
padding: 0 var(--container-paddding);
color: var(--vscode-foreground);
font-size: var(--vscode-font-size);
font-weight: var(--vscode-font-weight);
font-family: var(--vscode-font-family);
background-color: transparent;
}

p {
line-height: var(--line-height);
}

ol,
ul {
padding-left: var(--container-paddding);
}

body > *,
form > * {
margin-block-start: var(--input-margin-vertical);
margin-block-end: var(--input-margin-vertical);
}

*:focus {
outline-color: var(--vscode-focusBorder) !important;
}

a {
color: var(--vscode-textLink-foreground);
}

a:hover,
a:active {
color: var(--vscode-textLink-activeForeground);
}

button {
border: none;
border-radius: 2px;
padding: var(--input-padding-vertical) var(--input-padding-horizontal);
width: 100%;
text-align: center;
outline: 1px solid transparent;
outline-offset: 2px !important;
color: var(--vscode-button-foreground);
background: var(--vscode-button-background);
margin: 0.6rem auto;
font: var(--vscode-font-family);
line-height: var(--line-height);
}

button:hover {
cursor: pointer;
background: var(--vscode-button-hoverBackground);
}

button:focus {
outline-color: var(--vscode-focusBorder);
}

button.secondary {
color: var(--vscode-button-secondaryForeground);
background: var(--vscode-button-secondaryBackground);
}

button.secondary:hover {
background: var(--vscode-button-secondaryHoverBackground);
}

.code-wrapper {
margin: -0.25rem auto 0.8rem 1rem;
}

code {
font-size: var(--vscode-editor-font-size);
font-family: var(--vscode-editor-font-family);
}
h3 {
margin-top: 1rem;
}

.cf-logo {
margin-bottom: -2px;
}

.binding-heading {
margin-top: 1.4rem;
}
11 changes: 11 additions & 0 deletions packages/cloudflare-workers-bindings-extension/media/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//@ts-check

// This script will be run within the webview itself
// It cannot access the main VS Code APIs directly.
(function () {
const vscode = acquireVsCodeApi();

document.querySelector(".add-binding")?.addEventListener("click", () => {
vscode.postMessage({ type: "addBinding" });
});
})();
30 changes: 30 additions & 0 deletions packages/cloudflare-workers-bindings-extension/media/reset.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
html {
box-sizing: border-box;
font-size: 13px;
}

*,
*:before,
*:after {
box-sizing: inherit;
}

body,
h1,
h2,
/* h3, */
h4,
h5,
h6,
p,
ol,
ul {
margin: 0;
padding: 0;
font-weight: normal;
}

img {
max-width: 100%;
height: auto;
}
5 changes: 5 additions & 0 deletions packages/cloudflare-workers-bindings-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@
},
"views": {
"cloudflare-workers": [
{
"type": "webview",
"id": "cloudflare-workers-bindings.home",
"name": "Home"
},
{
"id": "cloudflare-workers-bindings",
"name": "Bindings",
Expand Down
10 changes: 9 additions & 1 deletion packages/cloudflare-workers-bindings-extension/src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as vscode from "vscode";
import { addBindingFlow } from "./add-binding";
import { HomeViewProvider } from "./home";
import { BindingsProvider, Node } from "./show-bindings";

export type Result = {
Expand Down Expand Up @@ -55,13 +56,20 @@ export async function activate(
}
);

const webviewProvider = new HomeViewProvider(context);
const homeWebView = vscode.window.registerWebviewViewProvider(
HomeViewProvider.viewType,
webviewProvider
);

// Cleanup when the extension is deactivated
context.subscriptions.push(
bindingsView,
watcher,
refreshCommand,
addBindingCommand,
openDocsCommand
openDocsCommand,
homeWebView
);

return {
Expand Down
98 changes: 98 additions & 0 deletions packages/cloudflare-workers-bindings-extension/src/home.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { randomBytes } from "node:crypto";
import * as vscode from "vscode";
import { addBindingFlow } from "./add-binding";

export class HomeViewProvider implements vscode.WebviewViewProvider {
public static readonly viewType = "cloudflare-workers-bindings.home";
constructor(private readonly _context: vscode.ExtensionContext) {}

public resolveWebviewView(
webviewView: vscode.WebviewView,
_context: vscode.WebviewViewResolveContext
) {
webviewView.webview.options = {
// Allow scripts in the webview
enableScripts: true,

localResourceRoots: [this._context.extensionUri],
};

webviewView.webview.html = this._getHtmlForWebview(webviewView.webview);

webviewView.webview.onDidReceiveMessage((data) => {
switch (data.type) {
case "addBinding": {
addBindingFlow(this._context);
break;
}
}
});
}

private _getHtmlForWebview(webview: vscode.Webview) {
// Get the local path to main script run in the webview, then convert it to a uri we can use in the webview.
const scriptUri = webview.asWebviewUri(
vscode.Uri.joinPath(this._context.extensionUri, "media", "main.js")
);
const styleResetUri = webview.asWebviewUri(
vscode.Uri.joinPath(this._context.extensionUri, "media", "reset.css")
);
const styleMainUri = webview.asWebviewUri(
vscode.Uri.joinPath(this._context.extensionUri, "media", "main.css")
);

// Use a nonce to only allow a specific script to be run.
const nonce = randomBytes(16).toString("base64");

return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--
Use a content security policy to only allow loading styles from our extension directory,
and only allow scripts that have a specific nonce.
-->
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource}; script-src 'nonce-${nonce}';">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="${styleResetUri}" rel="stylesheet">
<link href="${styleMainUri}" rel="stylesheet">
<title>Cloudflare Workers Home</title>
</head>
<body>
<h3>
<svg class="cf-logo" width="16" height="16" viewBox="0 0 16 16" fill="#F6821F" xmlns="http://www.w3.org/2000/svg">
<path
d="M6.21003 12.2925L2.99503 7.99255L6.19253 3.81505L5.57503 2.97255L1.97253 7.68505L1.96753 8.28755L5.58753 13.135L6.21003 12.2925Z"
fill="#F6821F" />
<path
d="M7.33253 1.98755H6.09503L10.5575 8.08755L6.20003 13.9875H7.44503L11.8 8.09005L7.33253 1.98755Z"
fill="#F6821F" />
<path
d="M9.72503 1.98755H8.47253L13.005 8.01505L8.47253 13.9875H9.72753L14.03 8.31755V7.71505L9.72503 1.98755Z"
fill="#F6821F" />
</svg>
Welcome to Cloudflare Workers</h3>
<p>Build serverless applications and deploy instantly across the globe for exceptional performance, reliability and scale.</p>
<a href="https://developers.cloudflare.com/workers/"><button>Read Workers documentation</button></a>
<h3>🚀 Get started</h3>
<p>To get started with a template, run:</p>
<p class="code-wrapper"><code>npm create cloudflare@latest</code></p>
<p>Develop your project locally:</p>
<p class="code-wrapper"><code>npx wrangler dev</code></p>
<p>When you're ready to deploy, run:</p>
<p class="code-wrapper"><code>npx wrangler deploy</code></p>
<h3 class="binding-heading">🔗 Bind to resources</h3>
<p>Connect your Worker to compute, storage and AI resources on the Developer Platform by configuring a <a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/">binding</a>.</p>
<button class="add-binding">Add new binding</button>
<script nonce="${nonce}" src="${scriptUri}"></script>
</body>
</html>`;
}
}

0 comments on commit 248bdb2

Please sign in to comment.