- Python mode via Pyodide WASM runtime with stdout/stderr console integration - Publish fiddles to clean /p/:slug URLs as standalone HTML pages - Import code from GitHub Gist URLs with auto-detection of language/mode - Presentation mode with slide management, fullscreen viewer, and keyboard nav - Enable Monaco color decorators for inline CSS color pickers - Extract reusable generateStandaloneHtml from export module
121 lines
3.3 KiB
JavaScript
121 lines
3.3 KiB
JavaScript
const BASE = '/api/fiddles';
|
|
|
|
async function request(url, opts = {}) {
|
|
const res = await fetch(url, {
|
|
headers: { 'Content-Type': 'application/json' },
|
|
...opts,
|
|
});
|
|
if (!res.ok) {
|
|
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
throw new Error(err.error || res.statusText);
|
|
}
|
|
return res.json();
|
|
}
|
|
|
|
export function createFiddle(data) {
|
|
return request(BASE, { method: 'POST', body: JSON.stringify(data) });
|
|
}
|
|
|
|
export function loadFiddle(id) {
|
|
return request(`${BASE}/${id}`);
|
|
}
|
|
|
|
export function updateFiddle(id, data) {
|
|
return request(`${BASE}/${id}`, { method: 'PUT', body: JSON.stringify(data) });
|
|
}
|
|
|
|
export function listFiddles({ q, js_type, tag, page, limit, sort } = {}) {
|
|
const params = new URLSearchParams();
|
|
if (q) params.set('q', q);
|
|
if (js_type) params.set('js_type', js_type);
|
|
if (tag) params.set('tag', tag);
|
|
if (page) params.set('page', String(page));
|
|
if (limit) params.set('limit', String(limit));
|
|
if (sort) params.set('sort', sort);
|
|
const qs = params.toString();
|
|
return request(`${BASE}${qs ? '?' + qs : ''}`);
|
|
}
|
|
|
|
export function listTags() {
|
|
return request('/api/tags');
|
|
}
|
|
|
|
// Version history
|
|
export function listVersions(id) {
|
|
return request(`${BASE}/${id}/versions`);
|
|
}
|
|
|
|
export function getVersion(id, ver) {
|
|
return request(`${BASE}/${id}/versions/${ver}`);
|
|
}
|
|
|
|
export function revertVersion(id, ver) {
|
|
return request(`${BASE}/${id}/revert/${ver}`, { method: 'POST' });
|
|
}
|
|
|
|
// Slides (presentation mode)
|
|
export function listSlides(fiddleId) {
|
|
return request(`${BASE}/${fiddleId}/slides`);
|
|
}
|
|
|
|
export function createSlide(fiddleId, data) {
|
|
return request(`${BASE}/${fiddleId}/slides`, { method: 'POST', body: JSON.stringify(data) });
|
|
}
|
|
|
|
export function updateSlide(slideId, data) {
|
|
return request(`/api/slides/${slideId}`, { method: 'PUT', body: JSON.stringify(data) });
|
|
}
|
|
|
|
export function deleteSlide(slideId) {
|
|
return request(`/api/slides/${slideId}`, { method: 'DELETE' });
|
|
}
|
|
|
|
// Gist import
|
|
export function importGist(url) {
|
|
return request('/api/import/gist', { method: 'POST', body: JSON.stringify({ url }) });
|
|
}
|
|
|
|
// Publishing
|
|
export function publishFiddle(id, html) {
|
|
return request(`${BASE}/${id}/publish`, { method: 'POST', body: JSON.stringify({ html }) });
|
|
}
|
|
|
|
export function unpublishFiddle(id) {
|
|
return request(`${BASE}/${id}/publish`, { method: 'DELETE' });
|
|
}
|
|
|
|
export function getPublishStatus(id) {
|
|
return request(`${BASE}/${id}/publish`);
|
|
}
|
|
|
|
// Collections
|
|
export function createCollection(data) {
|
|
return request('/api/collections', { method: 'POST', body: JSON.stringify(data) });
|
|
}
|
|
|
|
export function listCollections() {
|
|
return request('/api/collections');
|
|
}
|
|
|
|
export function getCollection(id) {
|
|
return request(`/api/collections/${id}`);
|
|
}
|
|
|
|
export function updateCollection(id, data) {
|
|
return request(`/api/collections/${id}`, { method: 'PUT', body: JSON.stringify(data) });
|
|
}
|
|
|
|
export function deleteCollection(id) {
|
|
return request(`/api/collections/${id}`, { method: 'DELETE' });
|
|
}
|
|
|
|
export function addToCollection(collectionId, fiddleId) {
|
|
return request(`/api/collections/${collectionId}/fiddles`, {
|
|
method: 'POST', body: JSON.stringify({ fiddle_id: fiddleId }),
|
|
});
|
|
}
|
|
|
|
export function removeFromCollection(collectionId, fiddleId) {
|
|
return request(`/api/collections/${collectionId}/fiddles/${fiddleId}`, { method: 'DELETE' });
|
|
}
|