Skip to content

Commit b46615e

Browse files
committed
feat(cdn): allows customization of the cdn base url
Allows for setting the CDN base url. Currently only tested is unpkg and https://cdn.jsdelivr.net/npm via the `cdnBaseUrl` property and config entry
1 parent c6051ca commit b46615e

10 files changed

Lines changed: 560 additions & 43 deletions

File tree

README.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ Set the `project-src` attribute or `projectSrc` property to a JSON file with for
213213
| `files.hidden` | If `true`, the file won't be visible in `playground-tab-bar`. |
214214
| `files.selected` | If `true`, this file's tab will be selected when the project is loaded. Only one file should have this field set. |
215215
| `extends` | Optional URL to another JSON config file to extend from. Configs are deeply merged. URLs are interpreted relative to the URL of each extendee config. |
216+
| `cdnBaseUrl` | Optional URL for the underlying npm CDN base url. Confirmed tested are `htts://unpkg.com` and `https://cdn.jsdelivr.net/npm` |
216217

217218
```html
218219
<playground-ide project-src="/path/to/my/project.json"> </playground-ide>
@@ -259,7 +260,7 @@ precedence. When either are set, inline scripts are ignored.
259260

260261
By default, bare module specifiers in JavaScript and TypeScript files are
261262
transformed to special `./node_modules/` URLs, and fetched behind-the-scenes
262-
from unpkg.com at the latest version.
263+
from unpkg.com by default at the latest version.
263264

264265
```js
265266
// What you write:
@@ -268,7 +269,7 @@ import {html} from 'lit';
268269
// What playground serves:
269270
import {html} from './node_modules/lit@2.0.2/index.js';
270271

271-
// What playground fetches behind-the-scenes:
272+
// What playground fetches behind-the-scenes unless you set `cdnBaseUrl`:
272273
// https://unpkg.com/lit@latest
273274
```
274275

@@ -335,7 +336,7 @@ When using inline project files, you can specify your import map like so:
335336
```
336337

337338
If an import map is defined, but does not contain an entry for a bare module,
338-
then playground defaults to the `unpkg.com` URL.
339+
then playground defaults to the `unpkg.com` URL unless `cdnBaseUrl` is set.
339340

340341
## TypeScript
341342

@@ -564,9 +565,10 @@ unprivileged and cannot modify the host window.
564565
You may wish to override this default sandbox base URL if you do not want a
565566
dependency on `unpkg.com`, e.g. for isolation from outages, or because your
566567
network does not have access to it. Note that Playground currently also uses
567-
`unpkg.com` to retrieve imported bare modules that are not otherwise handled by
568-
an [import map](#module-resolution), so the `unpkg.com` dependency cannot
569-
currently be completely eliminated.
568+
`unpkg.com` by default (unless you set `cdnBaseUrl`) to retrieve imported bare
569+
modules that are not otherwise handled by an [import map](#module-resolution),
570+
so to remove the dependency on unpkg, you should also set `cdnBaseUrl`. See the
571+
API docs for more info.
570572

571573
### Background
572574

@@ -680,6 +682,7 @@ All-in-one project, editor, file switcher, and preview with a horizontal side-by
680682
| -------------------- | -------------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
681683
| `projectSrc` | `string` | `undefined` | URL of the [project manifest](#project-manifest) to load |
682684
| `config` | `ProjectManifest` | `undefined` | Get or set the project configuration and files, ([details](#option-3-config-property)). |
685+
| `cdnBaseUrl` | `string` | `https://unpkg.com` | Change the underlying npm CDN base url. Confirmed tested are `htts://unpkg.com` and `https://cdn.jsdelivr.net/npm` |
683686
| `lineNumbers` | `boolean` | `false` | Render a gutter with line numbers in the editor |
684687
| `lineWrapping` | `boolean` | `false` | If `true`, long lines are wrapped, otherwise the editor will scroll. |
685688
| `editableFileSystem` | `boolean` | `false` | Allow adding, removing, and renaming files |
@@ -710,6 +713,7 @@ project element.
710713
| ---------------- | ----------------------------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
711714
| `projectSrc` | `string` | `undefined` | URL of a [project files manifest](#option-2-json-manifest) to load. |
712715
| `config` | `ProjectManifest` | `undefined` | Get or set the project configuration and files, ([details](#option-3-config-property)). |
716+
| `cdnBaseUrl` | `string` | `https://unpkg.com` | Change the underlying npm CDN base url. Confirmed tested are `htts://unpkg.com` and `https://cdn.jsdelivr.net/npm` |
713717
| `sandboxScope` | `string` | `"playground-elements"` | The service worker scope to register on. |
714718
| `sandboxBaseUrl` | `string` | _module parent directory_ | Base URL for untrusted JavaScript execution (⚠️ use with caution, see [sandbox security](#sandbox-security)). Resolved relative to the module containing the definition of `<playground-project>`. |
715719
| `diagnostics` | `Map<string, lsp.Diagnostic>` | `undefined` | Map from filename to array of Language Server Protocol diagnostics resulting from the latest compilation. |

configurator/project/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"dependencies": {
3-
"lit": "^2.0.0",
4-
"@lit/reactive-element": "^1.0.0",
5-
"lit-element": "^3.0.0",
6-
"lit-html": "^2.0.0"
3+
"lit": "^3.0.0",
4+
"@lit/reactive-element": "^2.0.0",
5+
"lit-element": "^4.0.0",
6+
"lit-html": "^3.0.0"
77
}
88
}

src/configurator/knobs.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ interface SelectKnob<Id extends string, T extends string>
4747
options: ReadonlyArray<T>;
4848
}
4949

50+
interface InputKnob<Id extends string> extends BaseKnob<Id, string> {
51+
type: 'input';
52+
placeholder?: string;
53+
inputType?: string;
54+
}
55+
5056
function checkbox<Id extends string>(
5157
def: Omit<CheckboxKnob<Id>, 'type'>
5258
): CheckboxKnob<Id> {
@@ -71,6 +77,12 @@ function select<Id extends string, T extends string>(
7177
return {type: 'select', ...def};
7278
}
7379

80+
function input<Id extends string>(
81+
def: Omit<InputKnob<Id>, 'type'>
82+
): InputKnob<Id> {
83+
return {type: 'input', ...def};
84+
}
85+
7486
const pixels = (value: number) => value + 'px';
7587

7688
export const knobs = [
@@ -120,6 +132,14 @@ export const knobs = [
120132
}),
121133

122134
// features
135+
input({
136+
id: 'cdnBaseUrl',
137+
label: 'CDN Base URL',
138+
section: 'features',
139+
default: 'https://unpkg.com',
140+
htmlAttribute: 'cdn-base-url',
141+
inputType: 'text',
142+
}),
123143
checkbox({
124144
id: 'resizable',
125145
label: 'Resizable',

src/configurator/playground-configurator.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ export class PlaygroundConfigurator extends LitElement {
130130
flex: 1;
131131
}
132132
133-
.knobs select {
133+
.knobs select,
134+
.knobs input[type='text'] {
134135
grid-column: 2 / -1;
135136
}
136137
@@ -263,6 +264,9 @@ export class PlaygroundConfigurator extends LitElement {
263264
case 'select':
264265
values.set(knob.id, urlValue);
265266
break;
267+
case 'input':
268+
values.set(knob.id, urlValue);
269+
break;
266270
default:
267271
throwUnreachable(knob, `Unexpected knob type ${(knob as Knob).type}`);
268272
}
@@ -290,6 +294,9 @@ export class PlaygroundConfigurator extends LitElement {
290294
case 'select':
291295
params.set(knob.id, value as string);
292296
break;
297+
case 'input':
298+
params.set(knob.id, value as string);
299+
break;
293300
default:
294301
throwUnreachable(knob, `Unexpected knob type ${(knob as Knob).type}`);
295302
}
@@ -332,6 +339,7 @@ export class PlaygroundConfigurator extends LitElement {
332339
.resizable=${this.values.getValue('resizable')}
333340
.editableFileSystem=${this.values.getValue('editableFileSystem')}
334341
.noCompletions=${this.values.getValue('noCompletions')}
342+
.cdnBaseUrl=${this.values.getValue('cdnBaseUrl')}
335343
project-src="./project/project.json"
336344
sandbox-base-url="."
337345
>
@@ -458,6 +466,9 @@ ${props.join('\n')}
458466
break;
459467
case 'checkbox':
460468
widget = this.checkboxKnob(knob);
469+
break;
470+
case 'input':
471+
widget = this.inputKnob(knob);
461472
}
462473
if (!widget) {
463474
return nothing;
@@ -561,6 +572,21 @@ ${props.join('\n')}
561572
`;
562573
}
563574

575+
private inputKnob(knob: KnobsOfType<'input'>) {
576+
const value = this.values.getValue(knob.id);
577+
return html`
578+
<input
579+
id=${knob.id}
580+
type="text"
581+
.value=${value}
582+
placeholder=${knob.placeholder || ''}
583+
@input=${(event: Event & {target: HTMLInputElement}) => {
584+
this.setValue(knob.id, event.target.value);
585+
}}
586+
/>
587+
`;
588+
}
589+
564590
private _openThemeDetector() {
565591
this._themeDetectorOpen = true;
566592
}

src/playground-ide.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,16 @@ export class PlaygroundIde extends LitElement {
217217
@property({attribute: 'sandbox-scope'})
218218
sandboxScope = `__playground_swfs_${serviceWorkerHash}/`;
219219

220+
/**
221+
* Base URL for the CDN used to resolve bare module specifiers.
222+
*
223+
* Examples:
224+
* - "https://unpkg.com" (default)
225+
* - "https://cdn.jsdelivr.net/npm"
226+
*/
227+
@property({attribute: 'cdn-base-url'})
228+
cdnBaseUrl = 'https://unpkg.com';
229+
220230
/**
221231
* Allow the user to add, remove, and rename files in the project's virtual
222232
* filesystem. Disabled by default.
@@ -299,6 +309,7 @@ export class PlaygroundIde extends LitElement {
299309
id=${projectId}
300310
.sandboxBaseUrl=${this.sandboxBaseUrl}
301311
.sandboxScope=${this.sandboxScope}
312+
.cdnBaseUrl=${this.cdnBaseUrl}
302313
>
303314
<slot></slot>
304315
</playground-project>

0 commit comments

Comments
 (0)