Skip to content

Commit ca8bd5b

Browse files
MarkTechsondylhunn
authored andcommitted
docs: add open in IDX support (angular#57099)
This change adds a menu to the in-browser code editor on adev and adds the option for open in IDX. PR Close angular#57099
1 parent 56816bb commit ca8bd5b

File tree

12 files changed

+273
-3
lines changed

12 files changed

+273
-3
lines changed

adev/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ APPLICATION_DEPS = [
8080
"@npm//@lezer/javascript",
8181
"@npm//@lezer/common",
8282
"@npm//@stackblitz/sdk",
83+
"@npm//open-in-idx",
8384
"@npm//@xterm/xterm",
8485
"@npm//@xterm/addon-fit",
8586
"@npm//algoliasearch",

adev/src/app/editor/code-editor/code-editor.component.html

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,23 @@
6868
<button
6969
class="adev-editor-download-button"
7070
type="button"
71-
(click)="openCurrentCodeInStackBlitz()"
72-
aria-label="Open current code in editor in StackBlitz"
71+
aria-label="Open current code in editor in an online editor"
72+
[cdkMenuTriggerFor]="launcherMenu"
7373
>
7474
<docs-icon>launch</docs-icon>
7575
</button>
76+
<!-- launcher dropdown window -->
77+
<ng-template #launcherMenu>
78+
<div class="adev-editor-dropdown" cdkMenu>
79+
<button cdkMenuItem (click)="openCurrentSolutionInIDX()">
80+
<span>Open in IDX </span>
81+
<img class="icon" src="assets/images/tutorials/common/idx_logo.svg" height="32">
82+
</button>
83+
<button cdkMenuItem (click)="openCurrentCodeInStackBlitz()">
84+
Open in StackBlitz
85+
</button>
86+
</div>
87+
</ng-template>
7688
<button
7789
class="adev-editor-download-button"
7890
type="button"

adev/src/app/editor/code-editor/code-editor.component.scss

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,34 @@
186186
}
187187
}
188188
}
189+
190+
.adev-editor-dropdown {
191+
border: 1px solid var(--senary-contrast);
192+
border-radius: 0.25rem;
193+
padding: 0;
194+
transform: translateY(-0.7rem);
195+
196+
button {
197+
background: var(--page-background);
198+
font-size: 0.875rem;
199+
width: 100%;
200+
text-align: left;
201+
padding-block: 0.5rem;
202+
color: var(--quaternary-contrast);
203+
transition: color 0.3s ease, background 0.3s ease;
204+
font-weight: 400;
205+
display: flex;
206+
justify-content: space-between;
207+
align-items: center;
208+
209+
&:hover {
210+
background: var(--senary-contrast);
211+
color: var(--primary-contrast);
212+
}
213+
.icon {
214+
margin: initial;
215+
padding: initial;
216+
width: auto;
217+
}
218+
}
219+
}

adev/src/app/editor/code-editor/code-editor.component.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import {DiagnosticWithLocation, DiagnosticsState} from './services/diagnostics-s
3131
import {DownloadManager} from '../download-manager.service';
3232
import {StackBlitzOpener} from '../stackblitz-opener.service';
3333
import {ClickOutside, IconComponent} from '@angular/docs';
34+
import {CdkMenu, CdkMenuItem, CdkMenuTrigger} from '@angular/cdk/menu';
35+
import {IDXLauncher} from '../idx-launcher.service';
3436

3537
export const REQUIRED_FILES = new Set([
3638
'src/main.ts',
@@ -46,7 +48,16 @@ const ANGULAR_DEV = 'https://angular.dev';
4648
templateUrl: './code-editor.component.html',
4749
styleUrls: ['./code-editor.component.scss'],
4850
changeDetection: ChangeDetectionStrategy.OnPush,
49-
imports: [NgIf, NgFor, MatTabsModule, IconComponent, ClickOutside],
51+
imports: [
52+
NgIf,
53+
NgFor,
54+
MatTabsModule,
55+
IconComponent,
56+
ClickOutside,
57+
CdkMenu,
58+
CdkMenuItem,
59+
CdkMenuTrigger,
60+
],
5061
})
5162
export class CodeEditor implements AfterViewInit, OnDestroy {
5263
@ViewChild('codeEditorWrapper') private codeEditorWrapperRef!: ElementRef<HTMLDivElement>;
@@ -78,6 +89,7 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
7889
private readonly diagnosticsState = inject(DiagnosticsState);
7990
private readonly downloadManager = inject(DownloadManager);
8091
private readonly stackblitzOpener = inject(StackBlitzOpener);
92+
private readonly idxLauncher = inject(IDXLauncher);
8193
private readonly title = inject(Title);
8294
private readonly location = inject(Location);
8395
private readonly embeddedTutorialManager = inject(EmbeddedTutorialManager);
@@ -117,6 +129,9 @@ export class CodeEditor implements AfterViewInit, OnDestroy {
117129
this.codeMirrorEditor.disable();
118130
}
119131

132+
openCurrentSolutionInIDX(): void {
133+
this.idxLauncher.openCurrentSolutionInIDX();
134+
}
120135
async openCurrentCodeInStackBlitz(): Promise<void> {
121136
const title = this.title.getTitle();
122137

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*!
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.dev/license
7+
*/
8+
9+
import {EnvironmentInjector, Injectable, inject} from '@angular/core';
10+
import {injectAsync} from '../core/services/inject-async';
11+
import * as IDX from 'open-in-idx';
12+
13+
@Injectable({
14+
providedIn: 'root',
15+
})
16+
export class IDXLauncher {
17+
private readonly environmentInjector = inject(EnvironmentInjector);
18+
19+
async openCurrentSolutionInIDX(): Promise<void> {
20+
const nodeRuntimeSandbox = await injectAsync(this.environmentInjector, () =>
21+
import('./node-runtime-sandbox.service').then((c) => c.NodeRuntimeSandbox),
22+
);
23+
24+
const runtimeFiles = await nodeRuntimeSandbox.getSolutionFiles();
25+
const workspaceFiles: Record<string, string> = {};
26+
27+
for (let i = 0; i < runtimeFiles.length; i++) {
28+
const file = runtimeFiles[i];
29+
30+
//don't include config.json, BUILD.bazel, package-lock.json, package.json.template
31+
const doNotAllowList = [
32+
'config.json',
33+
'BUILD.bazel',
34+
'package-lock.json',
35+
'package.json.template',
36+
];
37+
38+
const path = file.path.replace(/^\//, '');
39+
40+
//don't include binary formats
41+
if (!doNotAllowList.includes(path) && typeof file.content === 'string') {
42+
if (path === 'idx/dev.nix') {
43+
workspaceFiles['.idx/dev.nix'] = file.content as string;
44+
} else {
45+
workspaceFiles[path] = file.content as string;
46+
}
47+
}
48+
}
49+
IDX.newAdhocWorkspace({files: workspaceFiles});
50+
}
51+
}
Lines changed: 14 additions & 0 deletions
Loading
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# To learn more about how to use Nix to configure your environment
2+
# see: https://developers.google.com/idx/guides/customize-idx-env
3+
{ pkgs, ... }: {
4+
# Which nixpkgs channel to use.
5+
channel = "stable-23.11"; # or "unstable"
6+
# Use https://search.nixos.org/packages to find packages
7+
packages = [
8+
pkgs.nodejs_18
9+
];
10+
# Sets environment variables in the workspace
11+
env = {};
12+
idx = {
13+
# Search for the extensions you want on https://open-vsx.org/ and use "publisher.id"
14+
extensions = [
15+
"angular.ng-template"
16+
];
17+
workspace = {
18+
# Runs when a workspace is first created with this \`dev.nix\` file
19+
onCreate = {
20+
npm-install = "npm install --no-audit --prefer-offline";
21+
};
22+
# To run something each time the environment is rebuilt, use the \`onStart\` hook
23+
};
24+
# Enable previews and customize configuration
25+
previews = {
26+
enable = true;
27+
previews = {
28+
web = {
29+
command = ["npm" "run" "start" "--" "--port" "$PORT" "--host" "0.0.0.0"];
30+
manager = "web";
31+
};
32+
};
33+
};
34+
};
35+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# To learn more about how to use Nix to configure your environment
2+
# see: https://developers.google.com/idx/guides/customize-idx-env
3+
{ pkgs, ... }: {
4+
# Which nixpkgs channel to use.
5+
channel = "stable-23.11"; # or "unstable"
6+
# Use https://search.nixos.org/packages to find packages
7+
packages = [
8+
pkgs.nodejs_18
9+
];
10+
# Sets environment variables in the workspace
11+
env = {};
12+
idx = {
13+
# Search for the extensions you want on https://open-vsx.org/ and use "publisher.id"
14+
extensions = [
15+
"angular.ng-template"
16+
];
17+
workspace = {
18+
# Runs when a workspace is first created with this \`dev.nix\` file
19+
onCreate = {
20+
npm-install = "npm install --no-audit --prefer-offline";
21+
};
22+
# To run something each time the environment is rebuilt, use the \`onStart\` hook
23+
};
24+
# Enable previews and customize configuration
25+
previews = {
26+
enable = true;
27+
previews = {
28+
web = {
29+
command = ["npm" "run" "start" "--" "--port" "$PORT" "--host" "0.0.0.0"];
30+
manager = "web";
31+
};
32+
};
33+
};
34+
};
35+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# To learn more about how to use Nix to configure your environment
2+
# see: https://developers.google.com/idx/guides/customize-idx-env
3+
{ pkgs, ... }: {
4+
# Which nixpkgs channel to use.
5+
channel = "stable-23.11"; # or "unstable"
6+
# Use https://search.nixos.org/packages to find packages
7+
packages = [
8+
pkgs.nodejs_18
9+
];
10+
# Sets environment variables in the workspace
11+
env = {};
12+
idx = {
13+
# Search for the extensions you want on https://open-vsx.org/ and use "publisher.id"
14+
extensions = [
15+
"angular.ng-template"
16+
];
17+
workspace = {
18+
# Runs when a workspace is first created with this \`dev.nix\` file
19+
onCreate = {
20+
npm-install = "npm install --no-audit --prefer-offline";
21+
};
22+
# To run something each time the environment is rebuilt, use the \`onStart\` hook
23+
};
24+
# Enable previews and customize configuration
25+
previews = {
26+
enable = true;
27+
previews = {
28+
web = {
29+
command = ["npm" "run" "start" "--" "--port" "$PORT" "--host" "0.0.0.0"];
30+
manager = "web";
31+
};
32+
};
33+
};
34+
};
35+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# To learn more about how to use Nix to configure your environment
2+
# see: https://developers.google.com/idx/guides/customize-idx-env
3+
{ pkgs, ... }: {
4+
# Which nixpkgs channel to use.
5+
channel = "stable-23.11"; # or "unstable"
6+
# Use https://search.nixos.org/packages to find packages
7+
packages = [
8+
pkgs.nodejs_18
9+
];
10+
# Sets environment variables in the workspace
11+
env = {};
12+
idx = {
13+
# Search for the extensions you want on https://open-vsx.org/ and use "publisher.id"
14+
extensions = [
15+
"angular.ng-template"
16+
];
17+
workspace = {
18+
# Runs when a workspace is first created with this \`dev.nix\` file
19+
onCreate = {
20+
npm-install = "npm install --no-audit --prefer-offline";
21+
};
22+
# To run something each time the environment is rebuilt, use the \`onStart\` hook
23+
};
24+
# Enable previews and customize configuration
25+
previews = {
26+
enable = true;
27+
previews = {
28+
web = {
29+
command = ["npm" "run" "start" "--" "--port" "$PORT" "--host" "0.0.0.0"];
30+
manager = "web";
31+
};
32+
};
33+
};
34+
};
35+
}

0 commit comments

Comments
 (0)