Skip to content

Commit d455f0b

Browse files
committed
feat: add gist import
1 parent 2be8cdc commit d455f0b

File tree

3 files changed

+117
-2
lines changed

3 files changed

+117
-2
lines changed

src/app.js

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Store from "./store.js";
2+
import importFromGist from "./gist.js";
23

34
const DEFAULT_SOURCE = `# Welcome to Ruby Next playground!
45
# Here you can write Ruby code and see how it will be transformed by Ruby Next.
@@ -158,10 +159,43 @@ export default class App {
158159
});
159160
}
160161

162+
const importDialog = document.getElementById("importDialog");
163+
164+
if (importDialog) {
165+
this.el
166+
.querySelector('[target="import-btn"]')
167+
.addEventListener("click", () => importDialog.show());
168+
169+
importDialog.addEventListener("submit", (e) => {
170+
e.preventDefault();
171+
172+
const input = e.target.querySelector('[name="gistId"]');
173+
const url = input.value;
174+
175+
importDialog.hide();
176+
177+
this.importGist(url);
178+
});
179+
180+
importDialog.addEventListener("click", (e) => {
181+
if (e.target.tagName !== "A" || !e.target.dataset.url) return;
182+
183+
e.preventDefault();
184+
185+
const url = e.target.dataset.url;
186+
187+
importDialog.hide();
188+
189+
this.importGist(url);
190+
});
191+
}
192+
161193
this.setCurrentVMVersion();
162194

163195
if (theme === "dark")
164196
document.documentElement.classList.add("sl-theme-dark");
197+
198+
this.loadExampleFromUrl();
165199
}
166200

167201
transpile(code, opts = {}) {
@@ -272,11 +306,35 @@ export default class App {
272306
content.innerHTML = examples
273307
.map(
274308
(key) =>
275-
`<a class="text-blue-600 dark:text-blue-200 hover:text-blue-500 dark:text-blue-100 cursor-pointer py-2 inline-block" href="#" data-key="${key}">${key}</a>`
309+
`<a class="text-blue-600 dark:text-blue-200 hover:text-blue-500 dark:hover:text-blue-100 cursor-pointer py-2 inline-block" href="#" data-key="${key}">${key}</a>`
276310
)
277311
.join("");
278312
}
279313

280314
dialog.show();
281315
}
316+
317+
async importGist(url) {
318+
try {
319+
const { id, code, config } = await importFromGist(url);
320+
321+
this.codeEditor.setValue(code);
322+
this.configEditor.setValue(config);
323+
324+
// Set URL fragment to include gist ID
325+
window.location.hash = `gist:${id}`;
326+
} catch (e) {
327+
alert(e.message);
328+
}
329+
}
330+
331+
async loadExampleFromUrl() {
332+
if (!window.location.hash) return;
333+
334+
const [type, id] = window.location.hash.slice(1).split(":");
335+
336+
if (type !== "gist") return;
337+
338+
await this.importGist(`https://gist.github.com/${id}`);
339+
}
282340
}

src/gist.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
const BASE_URL = "https://api.github.com/gists/";
2+
3+
export default async function importFromGist(gistUrl) {
4+
const id = gistUrl.split("/").pop();
5+
6+
const url = `${BASE_URL}${id}`;
7+
8+
const response = await fetch(url);
9+
10+
if (!response.ok) {
11+
throw new Error(`Gist ${id} not found`);
12+
}
13+
14+
const data = await response.json();
15+
16+
if (!data.files) {
17+
throw new Error(`Gist has no files`);
18+
}
19+
20+
const config = data.files["config.rb"].content;
21+
const code = data.files["example.rb"].content;
22+
23+
if (!config || !code) {
24+
throw new Error(`Gist must have example.rb and config.rb files`);
25+
}
26+
27+
return { config, code, id };
28+
}

src/index.html

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ <h1 class="text-2xl">Playground</h1>
105105
</label>
106106
</div>
107107
<div class="flex flex-row mr-4 space-x-2">
108+
<span target="import-btn" class="mb-1 p-1 flex flex-row items-center cursor-pointer border dark:border-editor-light border-editor-dark">
109+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
110+
<path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
111+
</svg>
112+
<span class="ml-1">Import</span>
113+
</span>
108114
<span target="open-btn" class="mb-1 p-1 flex flex-row items-center cursor-pointer border dark:border-editor-light border-editor-dark">
109115
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
110116
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 9.776c.112-.017.227-.026.344-.026h15.812c.117 0 .232.009.344.026m-16.5 0a2.25 2.25 0 0 0-1.883 2.542l.857 6a2.25 2.25 0 0 0 2.227 1.932H19.05a2.25 2.25 0 0 0 2.227-1.932l.857-6a2.25 2.25 0 0 0-1.883-2.542m-16.5 0V6A2.25 2.25 0 0 1 6 3.75h3.879a1.5 1.5 0 0 1 1.06.44l2.122 2.12a1.5 1.5 0 0 0 1.06.44H18A2.25 2.25 0 0 1 20.25 9v.776" />
@@ -153,7 +159,30 @@ <h1 class="text-2xl">Playground</h1>
153159
</sl-dialog>
154160
<sl-dialog id="openDialog" label="Open example" class="dialog-overview">
155161
<div target="list" class="flex flex-col space-y-2">
156-
<a class="text-blue-600 dark:text-blue-200 hover:text-blue-500 dark:text-blue-100 cursor-pointer" href="#" data-key="${key}">${key}</a>
162+
<a class="text-blue-600 dark:text-blue-200 hover:text-blue-500 dark:hover:text-blue-100 cursor-pointer" href="#" data-key="${key}">${key}</a>
163+
</div>
164+
</sl-dialog>
165+
<sl-dialog id="importDialog" label="Open example" class="dialog-overview">
166+
<p>You can import examples from Gist by pasting a link below.</p>
167+
168+
<p class="text-sm my-2">
169+
<strong>NOTE:</strong>The Gist must contain <code>config.rb</code> and <code>example.rb</code> Ruby files.
170+
</p>
171+
172+
<form class="mt-2 flex flex-col space-y-2">
173+
<sl-input name="gistId" placeholder="Gist link" required></sl-input>
174+
<sl-button type="submit" submit>Import</sl-button>
175+
</form>
176+
177+
<div class="mt-4">
178+
You can also checkout these examples:
179+
180+
<ul class="flex flex-col space-y-2 list-disc list-inside">
181+
<li>
182+
<a class="text-blue-600 dark:text-blue-200 hover:text-blue-500 dark:hover:text-blue-100 cursor-pointer" href="#" data-url="https://gist.github.com/palkan/bf3a796268a9730a095fb26cf7f51410">Endless memoized methods</a>
183+
(<a class="text-blue-600 dark:text-blue-200 hover:text-blue-500 dark:hover:text-blue-100 cursor-pointer" href="https://gist.github.com/palkan/bf3a796268a9730a095fb26cf7f51410" target="_blank">gist</a>)
184+
</li>
185+
</ul>
157186
</div>
158187
</sl-dialog>
159188
</div>

0 commit comments

Comments
 (0)