API Specification Drafter

API Specification Drafter

API Spec Drafter

Design, Visualize, and Export OpenAPI Specifications

Endpoints

Select an endpoint to edit or create a new one.


        

${ep.summary}

${ep.description}

${paramsHtml}
Response Example
${ep.response}
`; }); container.innerHTML = html; } function renderJSON() { // Convert internal format to OpenAPI 3.0 Structure (Simplified) const openApi = { openapi: "3.0.0", info: { title: apiData.title, version: apiData.version }, paths: {} }; apiData.endpoints.forEach(ep => { if(!openApi.paths[ep.path]) openApi.paths[ep.path] = {}; const method = ep.method.toLowerCase(); openApi.paths[ep.path][method] = { summary: ep.summary, description: ep.description, parameters: ep.parameters.map(p => ({ name: p.name, in: p.in, schema: { type: p.type }, description: p.description })), responses: { "200": { description: "Successful response", content: { "application/json": { example: JSON.parse(ep.response || '{}') } } } } }; }); // Simple syntax highlighting const jsonStr = JSON.stringify(openApi, null, 2); const highlighted = jsonStr.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) { let cls = 'json-num'; if (/^"/.test(match)) { if (/:$/.test(match)) { cls = 'json-key'; } else { cls = 'json-str'; } } else if (/true|false/.test(match)) { cls = 'json-bool'; } else if (/null/.test(match)) { cls = 'json-bool'; } return '' + match + ''; }); document.getElementById('json-output').innerHTML = highlighted; } // --- Sample Data --- window.loadSample = function() { apiData.endpoints = [ { id: '1', method: 'GET', path: '/users', summary: 'List Users', description: 'Returns a paginated list of users.', parameters: [ {name: 'page', in: 'query', type: 'integer', description: 'Page number'}, {name: 'limit', in: 'query', type: 'integer', description: 'Items per page'} ], response: '[\n {\n "id": 1,\n "name": "Alice"\n }\n]' }, { id: '2', method: 'POST', path: '/users', summary: 'Create User', description: 'Creates a new user record.', parameters: [], response: '{\n "success": true,\n "id": 2\n}' } ]; renderList(); selectEndpoint('1'); }; // --- PDF Export --- window.exportPDF = async function() { // Ensure Docs tab is rendered switchView('preview'); const btn = document.querySelector('.api-btn-primary'); // Quick grab const origText = btn.innerHTML; btn.innerHTML = ' Processing...'; const element = document.getElementById('doc-render'); try { const canvas = await html2canvas(element, { scale: 2 }); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF('p', 'mm', 'a4'); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = pdf.internal.pageSize.getHeight(); const imgProps = pdf.getImageProperties(imgData); const imgHeight = (imgProps.height * pdfWidth) / imgProps.width; let heightLeft = imgHeight; let position = 0; pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, imgHeight); heightLeft -= pdfHeight; while (heightLeft >= 0) { position = heightLeft - imgHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', 0, position, pdfWidth, imgHeight); heightLeft -= pdfHeight; } pdf.save("API_Documentation.pdf"); } catch (err) { console.error(err); alert("Error generating PDF"); } finally { btn.innerHTML = origText; } }; // Init loadSample(); // Load sample on start for UX });
Scroll to Top