@stainless-api/playgrounds 0.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +23 -0
  3. package/eslint.config.js +2 -0
  4. package/package.json +69 -0
  5. package/src/Logs.tsx +216 -0
  6. package/src/Panel.tsx +21 -0
  7. package/src/PlaygroundPanelWrapper.tsx +5 -0
  8. package/src/build-py-types.ts +152 -0
  9. package/src/build-ts-types.ts +70 -0
  10. package/src/build.ts +97 -0
  11. package/src/codemirror/comlink.ts +698 -0
  12. package/src/codemirror/curl/curlconverter.vendor.js +7959 -0
  13. package/src/codemirror/curl.ts +108 -0
  14. package/src/codemirror/deps.ts +12 -0
  15. package/src/codemirror/fix-lsp-markdown.ts +50 -0
  16. package/src/codemirror/lsp.ts +87 -0
  17. package/src/codemirror/python/anser.ts +398 -0
  18. package/src/codemirror/python/pyodide.ts +180 -0
  19. package/src/codemirror/python.ts +160 -0
  20. package/src/codemirror/react.tsx +615 -0
  21. package/src/codemirror/sanitize-html.ts +12 -0
  22. package/src/codemirror/shiki.ts +65 -0
  23. package/src/codemirror/typescript/cdn-typescript.d.ts +1 -0
  24. package/src/codemirror/typescript/cdn-typescript.js +1 -0
  25. package/src/codemirror/typescript/console.ts +590 -0
  26. package/src/codemirror/typescript/get-signature.ts +94 -0
  27. package/src/codemirror/typescript/prettier-plugin-external-typescript.vendor.js +4968 -0
  28. package/src/codemirror/typescript/runner.ts +396 -0
  29. package/src/codemirror/typescript/special-info.ts +171 -0
  30. package/src/codemirror/typescript/worker.ts +292 -0
  31. package/src/codemirror/typescript.tsx +198 -0
  32. package/src/create.tsx +44 -0
  33. package/src/icon.tsx +21 -0
  34. package/src/index.ts +6 -0
  35. package/src/logs-context.ts +5 -0
  36. package/src/playground.css +359 -0
  37. package/src/sandbox-worker/in-frame.js +179 -0
  38. package/src/sandbox-worker/index.ts +202 -0
  39. package/src/use-storage.ts +54 -0
  40. package/src/util.ts +29 -0
  41. package/src/virtual-module.d.ts +45 -0
  42. package/src/vite-env.d.ts +1 -0
  43. package/test/get-signature.test.ts +73 -0
  44. package/test/use-storage.test.ts +60 -0
  45. package/tsconfig.json +11 -0
@@ -0,0 +1,359 @@
1
+ .stldocs-snippet-playground {
2
+ .playground-footer {
3
+ gap: 0.5rem;
4
+ font-family: var(--stl-typography-font);
5
+ display: flex;
6
+ padding: 0.5rem;
7
+ border-top: 1px solid var(--stl-color-border);
8
+ }
9
+ .stldocs-snippet-request {
10
+ background: var(--stl-color-background);
11
+ }
12
+ .stldocs-snippet-request-title {
13
+ padding-left: 0.5rem;
14
+ }
15
+ .cm-editor {
16
+ background-color: var(--stl-color-background);
17
+ }
18
+ .cm-editor .cm-gutters {
19
+ background-color: var(--stl-color-background);
20
+ }
21
+ pre,
22
+ code {
23
+ white-space: pre-wrap;
24
+ font-family: var(--stl-typography-font-mono);
25
+ font-size: inherit;
26
+ }
27
+
28
+ .cm-lsp-documentation {
29
+ padding: 0;
30
+ }
31
+ .cm-tooltip,
32
+ .cm-tooltip-autocomplete > ul {
33
+ scrollbar-width: thin;
34
+ scrollbar-color: var(--stl-color-border) transparent;
35
+ }
36
+ .cm-tooltip {
37
+ font-family: var(--stl-typography-font);
38
+ font-size: 0.8rem;
39
+ background: var(--stl-color-background);
40
+ border: 1px solid var(--stl-color-border);
41
+ border-radius: 0.5em;
42
+ box-shadow: 0px 4px 4px -2px #00000014;
43
+ line-height: 1.5;
44
+ width: max-content;
45
+ max-width: min(100%, 35rem);
46
+ max-height: 20rem;
47
+ overflow-y: auto;
48
+
49
+ .cm-tooltip-section {
50
+ padding: 0.25rem 0.5rem;
51
+ &.cm-tooltip-lint {
52
+ padding: 0;
53
+ .cm-diagnostic {
54
+ padding: 0.25rem 0.5rem;
55
+ }
56
+ }
57
+
58
+ p,
59
+ pre {
60
+ margin: 0;
61
+ }
62
+
63
+ a {
64
+ color: var(--stl-color-blue-foreground);
65
+ }
66
+
67
+ code {
68
+ font-family: var(--stl-typography-font-mono);
69
+ }
70
+
71
+ strong {
72
+ font-weight: bold;
73
+ }
74
+
75
+ h1,
76
+ h2,
77
+ h3,
78
+ h4,
79
+ h5 {
80
+ font-size: inherit;
81
+ letter-spacing: inherit;
82
+ line-height: inherit;
83
+ }
84
+
85
+ em {
86
+ font-style: italic;
87
+ }
88
+
89
+ p {
90
+ display: block;
91
+ }
92
+
93
+ li {
94
+ display: list-item;
95
+ }
96
+
97
+ ol,
98
+ ul {
99
+ display: block;
100
+ list-style-type: initial;
101
+ margin: 0;
102
+ padding: 0;
103
+ padding-left: 1em;
104
+ }
105
+
106
+ ol {
107
+ list-style-type: decimal;
108
+ }
109
+ }
110
+ hr {
111
+ border: none;
112
+ border-bottom: 1px solid var(--stl-color-border);
113
+ margin: 0.5em 0;
114
+ box-shadow:
115
+ -1rem 0 var(--stl-color-border),
116
+ 1rem 0 var(--stl-color-border);
117
+ }
118
+ &.cm-tooltip-autocomplete {
119
+ padding: 4px;
120
+ li {
121
+ border-radius: calc(0.5rem - 4px);
122
+ padding: 0.25rem 0.5rem;
123
+ }
124
+ }
125
+ }
126
+ .cm-scroller {
127
+ font-family: var(--stl-typography-font-mono);
128
+ line-height: 1.75;
129
+ scrollbar-color: var(--stl-color-border) transparent;
130
+ }
131
+ .cm-content {
132
+ padding-block: 1rem;
133
+ }
134
+ .cm-gutters {
135
+ border: none;
136
+ color: var(--stl-color-foreground-muted);
137
+ .cm-lineNumbers .cm-gutterElement {
138
+ opacity: 0.5;
139
+ text-align: right;
140
+ padding-left: 1rem;
141
+ padding-right: 0.5rem;
142
+ }
143
+ .cm-foldGutter {
144
+ width: calc(2rem / 3);
145
+ }
146
+ }
147
+ .cm-line {
148
+ padding: 0 0.35rem;
149
+ }
150
+ .playground-spacer {
151
+ flex-grow: 1;
152
+ }
153
+ :root[data-theme='dark'] & {
154
+ span[style*='--shiki-dark'] {
155
+ color: var(--shiki-dark) !important;
156
+ font-style: var(--shiki-dark-font-style) !important;
157
+ font-weight: var(--shiki-dark-font-weight) !important;
158
+ text-decoration: var(--shiki-dark-text-decoration) !important;
159
+ }
160
+ }
161
+ .playground-editor-load-error {
162
+ padding: 1rem;
163
+ overflow-y: auto;
164
+ }
165
+ .playground-logs {
166
+ display: block;
167
+ height: 14rem;
168
+ resize: vertical;
169
+ overflow-y: auto;
170
+ border-bottom-left-radius: 12px;
171
+ border-bottom-right-radius: 12px;
172
+ padding: 0;
173
+ }
174
+ .playground-logs li {
175
+ font-family: var(--stl-typography-font-mono);
176
+ font-size: var(--stl-typography-text-code);
177
+ padding: 0.5rem 1rem;
178
+ word-wrap: break-word;
179
+ word-break: break-word;
180
+ white-space: pre-wrap;
181
+ display: flex;
182
+ align-items: self-start;
183
+ grid-gap: 0.5em;
184
+ border-top: 1px solid var(--stl-playground-logs-border-color-prev, var(--stl-color-border));
185
+ }
186
+ .playground-logs li:first-child {
187
+ border-top: none;
188
+ }
189
+ .playground-logs li:where(:last-child) {
190
+ border-bottom: 1px solid var(--stl-color-border);
191
+ margin-bottom: 1rem;
192
+ }
193
+ .playground-logs li.playground-logs-blankslate {
194
+ display: flex;
195
+ flex-direction: column;
196
+ align-items: center;
197
+ text-align: center;
198
+ padding: 1.5rem 0;
199
+ color: var(--stl-color-foreground-reduced);
200
+ gap: 0.5rem;
201
+ border: none;
202
+ }
203
+
204
+ .playground-logs
205
+ li:is(.playground-log-stdout, .playground-log-stderr)
206
+ + li:is(.playground-log-stdout, .playground-log-stderr) {
207
+ border-top: none;
208
+ padding-top: 0;
209
+ }
210
+
211
+ .playground-logs li > .stldocs-icon {
212
+ width: 16px;
213
+ height: 16px;
214
+ flex-shrink: 0;
215
+
216
+ :is(.playground-log-stdout, .playground-log-stderr) & {
217
+ display: none;
218
+ }
219
+ }
220
+
221
+ .playground-logs li.playground-log-error {
222
+ color: var(--stl-color-red);
223
+ background-color: var(--stl-color-red-muted-background);
224
+ border-color: var(--stl-color-red-border);
225
+
226
+ & + li {
227
+ --stl-playground-logs-border-color-prev: var(--stl-color-red-border);
228
+ }
229
+ }
230
+
231
+ .playground-logs li.playground-log-warn {
232
+ color: var(--stl-color-yellow);
233
+ background-color: var(--stl-color-yellow-muted-background);
234
+ border-color: var(--stl-color-yellow-border);
235
+
236
+ & + li {
237
+ --stl-playground-logs-border-color-prev: var(--stl-color-yellow-border);
238
+ }
239
+ }
240
+
241
+ .playground-logs .playground-logs-object-toggle {
242
+ display: inline-block;
243
+ vertical-align: bottom;
244
+ cursor: pointer;
245
+ font: inherit;
246
+ line-height: 1;
247
+ margin: 0;
248
+ margin-right: 0.125em;
249
+ transform: translateY(-2px) rotate(0deg);
250
+ transition: 150ms ease transform;
251
+ appearance: none;
252
+ background: transparent;
253
+ padding: 0;
254
+ color: var(--stl-color-foreground);
255
+ border: none;
256
+ &.playground-logs-object-toggle-open {
257
+ transform: translateY(-2px) rotate(90deg);
258
+ }
259
+ & .stldocs-icon {
260
+ display: block;
261
+ }
262
+ }
263
+
264
+ .playground-logs .playground-logs-object-properties > *,
265
+ .playground-logs > li:not(.playground-log-stdout, .playground-log-stderr) .playground-logs-content {
266
+ display: block;
267
+ text-indent: -2ch;
268
+ margin-left: 2ch;
269
+ }
270
+
271
+ :is(.playground-log-stdout, playground-log-stderr)
272
+ .playground-logs-object-properties:not(
273
+ .playground-logs-object-properties .playground-logs-object-properties
274
+ ) {
275
+ padding-left: 2ch;
276
+ }
277
+
278
+ .playground-panel {
279
+ background: color-mix(in srgb, var(--stl-color-background), transparent);
280
+ }
281
+ .playground-panel-header {
282
+ font-family: var(--stl-typography-font);
283
+ font-size: 1rem;
284
+ display: flex;
285
+ align-items: center;
286
+ padding: 0.5rem 0.5rem 0.5rem 1rem;
287
+ border-bottom: 1px solid var(--stl-color-border);
288
+ height: 3rem;
289
+ .playground-panel:not(:first-of-type) & {
290
+ border-top: 1px solid var(--stl-color-border);
291
+ }
292
+ }
293
+ .playground-panel-header h5.playground-panel-title:not(:root) {
294
+ margin-inline: 0.5rem;
295
+ flex-grow: 1;
296
+ font-weight: 400;
297
+ font-style: normal;
298
+ line-height: 100%;
299
+ font-size: var(--stl-typography-scale-base);
300
+ font-family: var(--stl-typography-font);
301
+ color: var(--stl-color-foreground);
302
+ }
303
+ .playground-panel-content {
304
+ background: color-mix(in oklch, var(--stl-color-background) 99%, var(--stl-color-foreground));
305
+ }
306
+
307
+ .playground-panel-wrapper {
308
+ border: 1px solid var(--stl-color-border);
309
+ border-radius: 12px;
310
+ overflow: hidden;
311
+ border-top-left-radius: 0;
312
+ border-top-right-radius: 0;
313
+
314
+ @media (min-width: 1280px) {
315
+ border: none;
316
+ margin-left: -0.5rem;
317
+ margin-right: -0.5rem;
318
+ margin-bottom: -0.5rem;
319
+ border-bottom-left-radius: 16px;
320
+ border-bottom-right-radius: 16px;
321
+ }
322
+ @media (max-width: 1279px) {
323
+ background-color: var(--stl-color-faint-background);
324
+ margin-top: -12px;
325
+ padding-top: 12px;
326
+ }
327
+ }
328
+ .playground-auth-panel {
329
+ display: grid;
330
+ grid-template-columns: max-content 1fr;
331
+ align-items: center;
332
+ font-family: var(--stl-typography-font);
333
+ font-size: var(--stl-typography-scale-base);
334
+ label {
335
+ width: 100%;
336
+ padding: 0.5rem 1rem;
337
+ padding-right: 0.5rem;
338
+ height: 100%;
339
+ display: flex;
340
+ align-items: center;
341
+ code {
342
+ font-family: var(--stl-typography-font-mono);
343
+ font-size: var(--stl-typography-text-code);
344
+ }
345
+ }
346
+ > :not(label, hr) {
347
+ margin: 0.5rem;
348
+ }
349
+ hr {
350
+ grid-column: 1 / 3;
351
+ border: none;
352
+ border-bottom: 1px solid var(--stl-color-border);
353
+ margin: 0 0.5rem;
354
+ }
355
+ .stldocs-input {
356
+ width: calc(100% - 1rem);
357
+ }
358
+ }
359
+ }
@@ -0,0 +1,179 @@
1
+ // @ts-check
2
+ const transferableNames = new Set([
3
+ 'OffscreenCanvas',
4
+ 'ImageBitmap',
5
+ 'MessagePort',
6
+ 'MediaSourceHandle',
7
+ 'ReadableStream',
8
+ 'WritableStream',
9
+ 'TransformStream',
10
+ 'AudioData',
11
+ 'VideoFrame',
12
+ 'RTCDataChannel',
13
+ 'ArrayBuffer',
14
+ ]);
15
+ function inWorker() {
16
+ const handler = (/** @type {MessageEvent} */ e) => {
17
+ /** @type {Blob|undefined} */
18
+ const blob = e.data.blob;
19
+ if (blob) {
20
+ removeEventListener('message', handler);
21
+ /** @type {any} */ (self).importScripts(URL.createObjectURL(blob));
22
+ }
23
+ };
24
+ addEventListener('message', handler);
25
+ }
26
+ /**
27
+ * @param {{ port: MessagePort; blob: Blob; options: WorkerOptions | undefined; }} params
28
+ */
29
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
30
+ function init(params) {
31
+ // top level URL must be `data` not `blob` because chrome doesn't inherit
32
+ // isSecureContext for blob urls for some reason.
33
+ const worker = new Worker(
34
+ 'data:text/javascript,' + encodeURIComponent(`(${inWorker.toString()})()`),
35
+ params.options,
36
+ );
37
+ worker.postMessage({ blob: params.blob });
38
+ const makeTransferList = (/** @type {any} */ value) => {
39
+ /**
40
+ * @type {any[]}
41
+ */
42
+ const arr = [];
43
+ walkValue(value, (value) => {
44
+ if (transferableNames.has(classOf(value))) {
45
+ arr.push(value);
46
+ }
47
+ });
48
+ return arr;
49
+ };
50
+ worker.addEventListener('error', (e) => {
51
+ e.preventDefault();
52
+ params.port.postMessage(
53
+ { type: 'error', error: e.error ?? new Error(e.message || 'Unknown Error') },
54
+ makeTransferList(e.error),
55
+ );
56
+ });
57
+ worker.addEventListener('message', (e) => {
58
+ e.preventDefault();
59
+ params.port.postMessage({ type: 'message', data: e.data }, makeTransferList(e.data));
60
+ });
61
+ worker.addEventListener('messageerror', (e) => {
62
+ e.preventDefault();
63
+ params.port.postMessage({ type: 'messageerror', data: e.data }, makeTransferList(e.data));
64
+ });
65
+ params.port.addEventListener('message', (e) => {
66
+ e.preventDefault();
67
+ if (e.data.type === 'postMessage') {
68
+ worker.postMessage(e.data.data, e.data.options);
69
+ }
70
+ if (e.data.type === 'terminate') {
71
+ worker.terminate();
72
+ }
73
+ });
74
+ params.port.postMessage({ type: 'ready' });
75
+ params.port.start();
76
+ }
77
+
78
+ const classOf = (/** @type {unknown} */ value) => Object.prototype.toString.call(value).slice(8, -1);
79
+
80
+ /**
81
+ * @param {unknown} it
82
+ */
83
+ function isObject(it) {
84
+ return typeof it == 'object' ? it !== null : isCallable(it);
85
+ }
86
+
87
+ // https://tc39.es/ecma262/#sec-IsHTMLDDA-internal-slot
88
+ var documentAll = typeof document == 'object' && document.all;
89
+
90
+ // `IsCallable` abstract operation
91
+ // https://tc39.es/ecma262/#sec-iscallable
92
+ const isCallable =
93
+ typeof documentAll == 'undefined' && documentAll !== undefined
94
+ ? function (/** @type {unknown} */ argument) {
95
+ return typeof argument == 'function' || argument === documentAll;
96
+ }
97
+ : function (/** @type {unknown} */ argument) {
98
+ return typeof argument == 'function';
99
+ };
100
+
101
+ /**
102
+ * @param {any} value
103
+ * @param {(value: unknown) => void=} fn
104
+ * @param {Set<unknown>=} set
105
+ * @returns {Set<any>}
106
+ */
107
+ function walkValue(value, fn, set) {
108
+ if (set) {
109
+ if (set.has(value)) return set;
110
+ } else set = new Set();
111
+ if (value === globalThis) return set;
112
+ if (!isObject(value)) return set;
113
+
114
+ fn?.(value);
115
+
116
+ var type = classOf(value);
117
+ var i;
118
+ var length;
119
+ var keys;
120
+ var key;
121
+ var child;
122
+
123
+ set.add(value);
124
+
125
+ switch (type) {
126
+ case 'DataView':
127
+ case 'Int8Array':
128
+ case 'Uint8Array':
129
+ case 'Uint8ClampedArray':
130
+ case 'Int16Array':
131
+ case 'Uint16Array':
132
+ case 'Int32Array':
133
+ case 'Uint32Array':
134
+ case 'Float16Array':
135
+ case 'Float32Array':
136
+ case 'Float64Array':
137
+ case 'BigInt64Array':
138
+ case 'BigUint64Array':
139
+ walkValue(value.buffer, fn, set);
140
+ break;
141
+ case 'Array':
142
+ case 'Object':
143
+ keys = Object.keys(value);
144
+ for (i = 0, length = keys.length; i < length; i++) {
145
+ key = /** @type {string} */ (keys[i]);
146
+ try {
147
+ child = value[key];
148
+ } catch {
149
+ continue;
150
+ }
151
+ walkValue(child, fn, set);
152
+ }
153
+ break;
154
+ case 'Map':
155
+ value.forEach(function (/** @type {any} */ v, /** @type {any} */ k) {
156
+ walkValue(k, fn, set);
157
+ walkValue(v, fn, set);
158
+ });
159
+ break;
160
+ case 'Set':
161
+ value.forEach(function (/** @type {any} */ v) {
162
+ walkValue(v, fn, set);
163
+ });
164
+ break;
165
+ case 'Error':
166
+ walkValue(value.message, fn, set);
167
+ if (Object.hasOwn(value, 'cause')) {
168
+ walkValue(value.cause, fn, set);
169
+ }
170
+ if (value.name === 'AggregateError') {
171
+ walkValue(value.errors, fn, set);
172
+ } else if (value.name === 'SuppressedError') {
173
+ walkValue(value.error, fn, set);
174
+ walkValue(value.suppressed, fn, set);
175
+ } // break omitted
176
+ }
177
+
178
+ return set;
179
+ }