@bluejeans/flexdoc-backend
Version:
FlexDoc backend integration for NestJS and other frameworks
866 lines (855 loc) • 36.6 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateFlexDocHTML = generateFlexDocHTML;
const nunjucks = __importStar(require("nunjucks"));
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
const templatesPath = path.join(__dirname, 'templates');
if (!fs.existsSync(templatesPath)) {
fs.mkdirSync(templatesPath, { recursive: true });
}
const nunjucksEnv = nunjucks.configure(templatesPath, {
autoescape: true,
trimBlocks: true,
lstripBlocks: true,
});
nunjucksEnv.addFilter('json', function (obj) {
return JSON.stringify(obj);
});
nunjucksEnv.addFilter('upper', function (str) {
return str.toUpperCase();
});
nunjucksEnv.addFilter('lower', function (str) {
return str.toLowerCase();
});
function generateFlexDocHTML(spec, options = {}) {
const { title = 'API Documentation', description = 'Interactive API documentation powered by FlexDoc', altDescription = '', theme = 'light', customCss = '', customJs = '', favicon = '', logo = '', specUrl, tagGroups, } = options;
const themeConfig = typeof theme === 'object' ? theme : {};
const themeMode = typeof theme === 'string' ? theme : 'light';
if (spec && tagGroups && spec.paths) {
const includedTags = new Set();
tagGroups.forEach((group) => {
group.tags.forEach((tag) => includedTags.add(tag));
});
const filteredPaths = {};
for (const path in spec.paths) {
const pathItem = spec.paths[path];
const filteredPathItem = {};
let hasIncludedOperation = false;
for (const method in pathItem) {
if (['get', 'post', 'put', 'delete', 'patch', 'options', 'head'].includes(method)) {
const operation = pathItem[method];
if (operation.tags &&
operation.tags.some((tag) => includedTags.has(tag))) {
filteredPathItem[method] = operation;
hasIncludedOperation = true;
}
}
else {
filteredPathItem[method] =
pathItem[method];
}
}
if (hasIncludedOperation) {
filteredPaths[path] = filteredPathItem;
}
}
spec.paths = filteredPaths;
if (spec.components?.schemas) {
const usedSchemaRefs = new Set();
const collectSchemaRefs = (obj) => {
if (!obj || typeof obj !== 'object')
return;
if (obj.$ref &&
typeof obj.$ref === 'string' &&
obj.$ref.startsWith('#/components/schemas/')) {
const schemaName = obj.$ref.replace('#/components/schemas/', '');
usedSchemaRefs.add(schemaName);
if (spec.components?.schemas?.[schemaName]) {
collectSchemaRefs(spec.components.schemas[schemaName]);
}
}
if (obj.items) {
collectSchemaRefs(obj.items);
}
if (obj.properties) {
Object.values(obj.properties).forEach((prop) => {
collectSchemaRefs(prop);
});
}
if (Array.isArray(obj)) {
obj.forEach((item) => collectSchemaRefs(item));
}
Object.values(obj).forEach((val) => {
if (val && typeof val === 'object') {
collectSchemaRefs(val);
}
});
};
Object.values(filteredPaths).forEach((pathItem) => {
collectSchemaRefs(pathItem);
});
const filteredSchemas = {};
for (const schemaName of usedSchemaRefs) {
if (spec.components.schemas[schemaName]) {
filteredSchemas[schemaName] = spec.components.schemas[schemaName];
}
}
spec.components.schemas = filteredSchemas;
}
}
const specJsonString = spec ? JSON.stringify(spec, null, 2) : '';
let logoUrl = '';
let logoStyle = '';
let logoContainerStyle = '';
let logoContainerClass = '';
let logoAlt = 'Logo';
let logoClickable = false;
if (logo) {
if (typeof logo === 'string') {
logoUrl = logo;
}
else {
logoUrl = logo.url;
logoAlt = logo.alt || 'Logo';
logoClickable = logo.clickable || false;
const logoStyles = [];
if (logo.maxHeight) {
logoStyles.push(`max-height: ${typeof logo.maxHeight === 'number'
? `${logo.maxHeight}px`
: logo.maxHeight}`);
}
if (logo.maxWidth) {
logoStyles.push(`max-width: ${typeof logo.maxWidth === 'number'
? `${logo.maxWidth}px`
: logo.maxWidth}`);
}
logoStyle =
logoStyles.length > 0 ? ` style="${logoStyles.join('; ')}"` : '';
const containerStyles = [];
if (logo.backgroundColor) {
containerStyles.push(`background-color: ${logo.backgroundColor}`);
}
if (logo.padding) {
if (typeof logo.padding === 'string') {
containerStyles.push(`padding: ${logo.padding}`);
}
else {
const vertical = logo.padding.vertical
? typeof logo.padding.vertical === 'number'
? `${logo.padding.vertical}px`
: logo.padding.vertical
: '0';
const horizontal = logo.padding.horizontal
? typeof logo.padding.horizontal === 'number'
? `${logo.padding.horizontal}px`
: logo.padding.horizontal
: '0';
containerStyles.push(`padding: ${vertical} ${horizontal}`);
}
}
logoContainerStyle =
containerStyles.length > 0
? ` style="${containerStyles.join('; ')}"`
: '';
logoContainerClass = logo.containerClass ? ` ${logo.containerClass}` : '';
}
}
const specData = spec ? JSON.stringify(spec, null, 2) : null;
const specSource = specUrl
? `fetch('${specUrl}').then(r => r.json())`
: `Promise.resolve(${specData})`;
const themeColors = themeConfig?.colors || {};
const isDarkMode = themeMode === 'dark';
const cssVars = [];
if (themeColors.primary) {
if (themeColors.primary.main)
cssVars.push(`--flexdoc-primary: ${themeColors.primary.main}`);
if (themeColors.primary.light)
cssVars.push(`--flexdoc-primary-light: ${themeColors.primary.light}`);
if (themeColors.primary.dark)
cssVars.push(`--flexdoc-primary-dark: ${themeColors.primary.dark}`);
}
if (themeColors.success) {
if (themeColors.success.main)
cssVars.push(`--flexdoc-success: ${themeColors.success.main}`);
if (themeColors.success.light)
cssVars.push(`--flexdoc-success-light: ${themeColors.success.light}`);
if (themeColors.success.dark)
cssVars.push(`--flexdoc-success-dark: ${themeColors.success.dark}`);
}
if (themeColors.error) {
if (themeColors.error.main)
cssVars.push(`--flexdoc-error: ${themeColors.error.main}`);
if (themeColors.error.light)
cssVars.push(`--flexdoc-error-light: ${themeColors.error.light}`);
if (themeColors.error.dark)
cssVars.push(`--flexdoc-error-dark: ${themeColors.error.dark}`);
}
if (themeColors.text) {
if (themeColors.text.primary)
cssVars.push(`--flexdoc-text-primary: ${themeColors.text.primary}`);
if (themeColors.text.secondary)
cssVars.push(`--flexdoc-text-secondary: ${themeColors.text.secondary}`);
}
if (themeColors.gray) {
if (themeColors.gray[50])
cssVars.push(`--flexdoc-gray-50: ${themeColors.gray[50]}`);
if (themeColors.gray[100])
cssVars.push(`--flexdoc-gray-100: ${themeColors.gray[100]}`);
}
if (themeColors.border) {
if (themeColors.border.dark)
cssVars.push(`--flexdoc-border-dark: ${themeColors.border.dark}`);
if (themeColors.border.light)
cssVars.push(`--flexdoc-border-light: ${themeColors.border.light}`);
}
if (themeConfig.typography) {
const typography = themeConfig.typography;
if (typography.fontSize)
cssVars.push(`--flexdoc-font-size: ${typography.fontSize}`);
if (typography.lineHeight)
cssVars.push(`--flexdoc-line-height: ${typography.lineHeight}`);
if (typography.fontFamily)
cssVars.push(`--flexdoc-font-family: ${typography.fontFamily}`);
if (typography.headings) {
if (typography.headings.fontFamily)
cssVars.push(`--flexdoc-headings-font-family: ${typography.headings.fontFamily}`);
if (typography.headings.fontWeight)
cssVars.push(`--flexdoc-headings-font-weight: ${typography.headings.fontWeight}`);
}
if (typography.code) {
if (typography.code.fontSize)
cssVars.push(`--flexdoc-code-font-size: ${typography.code.fontSize}`);
if (typography.code.fontFamily)
cssVars.push(`--flexdoc-code-font-family: ${typography.code.fontFamily}`);
if (typography.code.lineHeight)
cssVars.push(`--flexdoc-code-line-height: ${typography.code.lineHeight}`);
if (typography.code.color)
cssVars.push(`--flexdoc-code-color: ${typography.code.color}`);
if (typography.code.backgroundColor)
cssVars.push(`--flexdoc-code-bg: ${typography.code.backgroundColor}`);
}
}
if (themeConfig.sidebar) {
const sidebar = themeConfig.sidebar;
if (sidebar.backgroundColor)
cssVars.push(`--flexdoc-sidebar-bg: ${sidebar.backgroundColor}`);
if (sidebar.textColor)
cssVars.push(`--flexdoc-sidebar-text: ${sidebar.textColor}`);
if (sidebar.activeTextColor)
cssVars.push(`--flexdoc-sidebar-active: ${sidebar.activeTextColor}`);
}
const cssVarsString = cssVars.length > 0 ? cssVars.join(';') + ';' : '';
const customThemeCSS = Object.entries(themeColors)
.map(([key, value]) => `--flexdoc-${key}: ${value};`)
.join('\n ');
const taggedPaths = {};
const tagNameMap = {};
if (options.tagGroups) {
options.tagGroups.forEach((group) => {
group.tags.forEach((tag) => {
tagNameMap[tag] = group.name;
});
});
}
if (spec) {
const paths = spec['paths'] || {};
for (const path in paths) {
const pathItem = paths[path];
for (const method in pathItem) {
if (['get', 'post', 'put', 'delete', 'patch', 'options', 'head'].includes(method)) {
const operation = pathItem[method];
const tags = operation.tags || ['default'];
for (const tag of tags) {
const tagName = tagNameMap[tag] || tag;
if (!taggedPaths[tagName]) {
taggedPaths[tagName] = {};
}
if (!taggedPaths[tagName][path]) {
taggedPaths[tagName][path] = {};
}
taggedPaths[tagName][path][method] = operation;
}
}
}
}
}
const tagNameMapForTemplate = Object.fromEntries(Object.entries(tagNameMap).map(([tag, name]) => [name, tag]));
const methodColors = {
get: 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300',
post: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300',
put: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300',
delete: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300',
patch: 'bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-300',
options: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300',
head: 'bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-300',
};
nunjucksEnv.addGlobal('getOperationId', (path, method, operation) => {
return (operation.operationId ||
`${method}-${path.replace(/[^a-zA-Z0-9]/g, '-')}`);
});
nunjucksEnv.addGlobal('getStatusCodeClass', (statusCode) => {
const code = parseInt(statusCode, 10);
if (code >= 200 && code < 300) {
return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300';
}
else if (code >= 300 && code < 400) {
return 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300';
}
else if (code >= 400 && code < 500) {
return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300';
}
else {
return 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300';
}
});
nunjucksEnv.addGlobal('getStatusText', (statusCode) => {
const statusTexts = {
'200': 'OK',
'201': 'Created',
'204': 'No Content',
'400': 'Bad Request',
'401': 'Unauthorized',
'403': 'Forbidden',
'404': 'Not Found',
'500': 'Internal Server Error',
};
return statusTexts[statusCode] || '';
});
nunjucksEnv.addGlobal('renderSchema', (schema) => {
function renderSchemaAsHTML(schema, indent = 0) {
if (!schema)
return '<span class="text-gray-400">null</span>';
if (schema.$ref) {
const refSchema = resolveSchemaRef(schema.$ref);
if (refSchema) {
return renderSchemaAsHTML(refSchema, indent);
}
return `<span class="text-red-500">Could not resolve reference: ${schema.$ref}</span>`;
}
if (schema.type === 'object' || (!schema.type && schema.properties)) {
let html = '<div class="pl-4">';
if (schema.properties) {
const properties = Object.entries(schema.properties);
properties.forEach(([propName, propSchema], index) => {
const isRequired = schema.required && schema.required.includes(propName);
const requiredBadge = isRequired
? '<span class="text-red-500 ml-1">*</span>'
: '';
html += `<div class="mb-2">
<span class="font-semibold text-blue-600 dark:text-blue-400">${propName}</span>${requiredBadge}: `;
html += renderSchemaAsHTML(propSchema, indent + 2);
if (propSchema.description) {
html += `<span class="text-gray-500 ml-2">// ${propSchema.description}</span>`;
}
html += '</div>';
});
}
html += '</div>';
return html;
}
else if (schema.type === 'array') {
return `<span class="text-purple-600 dark:text-purple-400">Array of:</span> ${renderSchemaAsHTML(schema.items, indent)}`;
}
else if (schema.enum) {
return `<span class="text-green-600 dark:text-green-400">${schema.type || 'enum'}</span> <span class="text-gray-500">(${schema.enum
.map((e) => JSON.stringify(e))
.join(' | ')})</span>`;
}
else {
let typeText = schema.type || 'any';
let formatText = schema.format ? ` (${schema.format})` : '';
return `<span class="text-green-600 dark:text-green-400">${typeText}${formatText}</span>`;
}
}
return renderSchemaAsHTML(schema);
});
nunjucksEnv.addGlobal('renderExample', (example) => {
return JSON.stringify(example, null, 2);
});
const baseUrl = spec?.servers?.[0]?.url || 'https://api.example.com';
function renderCodeExamples(path, method, operation) {
return {
curl: renderCurlExample(path, method, operation, baseUrl),
python: renderPythonExample(path, method, operation, baseUrl),
javascript: renderJavaScriptExample(path, method, operation, baseUrl),
go: renderGoExample(path, method, operation, baseUrl),
};
}
function renderCurlExample(path, method, operation, baseUrl) {
let url = `${baseUrl}${path}`;
const params = operation.parameters?.filter((p) => p.in === 'path') || [];
params.forEach((param) => {
const paramName = param.name;
url = url.replace(`{${paramName}}`, `${paramName}_value`);
});
const queryParams = operation.parameters?.filter((p) => p.in === 'query') || [];
if (method.toLowerCase() === 'get' && queryParams.length > 0) {
url +=
'?' + queryParams.map((p) => `${p.name}=${p.name}_value`).join('&');
}
let headers = 'Content-Type: application/json';
let body = '';
if (method.toLowerCase() !== 'get' &&
operation.requestBody?.content?.['application/json']) {
try {
const schema = operation.requestBody.content['application/json'].schema;
if (!schema) {
body = ` \\
-d '{ "example": "No schema available" }'`;
return `curl -X ${method.toUpperCase()} \\
"${url}" \\
-H "${headers}"${body}`;
}
const exampleBody = generateExampleFromSchema(schema);
const jsonString = JSON.stringify(exampleBody, null, 2);
const escapedJson = jsonString
.replace(/"/g, '\\"')
.replace(/\n/g, '\\n');
body = ` \\
-d '${escapedJson}'`;
}
catch (error) {
console.error('Error generating request body:', error);
body = ` \\
-d '{ "error": "Failed to generate example" }'`;
}
}
return `curl -X ${method.toUpperCase()} \\
"${url}" \\
-H "${headers}"${body}`;
}
function resolveSchemaRef(ref) {
if (!ref.startsWith('#/')) {
return null;
}
const path = ref.substring(2).split('/');
let current = spec;
for (const segment of path) {
if (current && current[segment]) {
current = current[segment];
}
else {
console.log('Could not resolve reference:', ref, 'at segment:', segment);
return null;
}
}
return current;
}
function generateExampleFromSchema(schema) {
if (!schema)
return null;
if (schema.$ref) {
const refSchema = resolveSchemaRef(schema.$ref);
if (refSchema) {
return generateExampleFromSchema(refSchema);
}
return { example: 'value' };
}
switch (schema.type) {
case 'object':
const obj = {};
if (schema.properties) {
for (const propName in schema.properties) {
obj[propName] = generateExampleFromSchema(schema.properties[propName]);
}
}
return obj;
case 'array':
if (schema.items) {
return [generateExampleFromSchema(schema.items)];
}
return [];
case 'string':
if (schema.enum && schema.enum.length > 0) {
return schema.enum[0];
}
if (schema.format === 'date-time')
return '2023-01-01T00:00:00Z';
if (schema.format === 'date')
return '2023-01-01';
if (schema.format === 'email')
return 'user@example.com';
if (schema.format === 'uuid')
return '00000000-0000-0000-0000-000000000000';
return 'string';
case 'number':
case 'integer':
if (schema.enum && schema.enum.length > 0) {
return schema.enum[0];
}
return 0;
case 'boolean':
return false;
default:
return null;
}
}
function renderPythonExample(path, method, operation, baseUrl) {
let url = `${baseUrl}${path}`;
const params = operation.parameters?.filter((p) => p.in === 'path') || [];
params.forEach((param) => {
const paramName = param.name;
url = url.replace(`{${paramName}}`, `${paramName}_value`);
});
const queryParams = operation.parameters?.filter((p) => p.in === 'query') || [];
let queryParamsCode = '';
if (queryParams.length > 0) {
queryParamsCode = `params = {\n ${queryParams
.map((p) => `"${p.name}": "${p.name}_value"`)
.join(',\n ')}\n}`;
}
let bodyCode = '';
if (method.toLowerCase() !== 'get' &&
operation.requestBody?.content?.['application/json']) {
const schema = operation.requestBody.content['application/json'].schema;
const exampleBody = generateExampleFromSchema(schema);
const jsonStr = JSON.stringify(exampleBody, null, 4)
.replace(/"/g, '\\"')
.replace(/\n/g, '\n ');
bodyCode = `payload = ${jsonStr}`;
}
return `import requests
${queryParamsCode ? queryParamsCode + '\n\n' : ''}${bodyCode ? bodyCode + '\n\n' : ''}headers = {\n "Content-Type": "application/json"\n}
response = requests.${method.toLowerCase()}("${url}"${queryParams.length > 0 ? ', params=params' : ''}${bodyCode ? ', json=payload' : ''}, headers=headers)
print(response.json())`;
}
function renderJavaScriptExample(path, method, operation, baseUrl) {
let url = `${baseUrl}${path}`;
const params = operation.parameters?.filter((p) => p.in === 'path') || [];
params.forEach((param) => {
const paramName = param.name;
url = url.replace(`{${paramName}}`, `${paramName}_value`);
});
const queryParams = operation.parameters?.filter((p) => p.in === 'query') || [];
let queryParamsCode = '';
if (queryParams.length > 0) {
const queryString = queryParams
.map((p) => `${p.name}=\${${p.name}Value}`)
.join('&');
queryParamsCode = `const ${queryParams
.map((p) => `${p.name}Value = "${p.name}_value"`)
.join(';\n')};
\nconst queryString = "${queryString}";
url = \`${url}?\${queryString}\`;`;
}
let bodyCode = '';
if (method.toLowerCase() !== 'get' &&
operation.requestBody?.content?.['application/json']) {
const schema = operation.requestBody.content['application/json'].schema;
const exampleBody = generateExampleFromSchema(schema);
const jsonStr = JSON.stringify(exampleBody, null, 2)
.replace(/"/g, '\\"')
.replace(/\n/g, '\n ');
bodyCode = `const payload = ${jsonStr};`;
}
return `// Using fetch API\nasync function callApi() {\n let url = "${url}";
${queryParamsCode ? queryParamsCode + '\n\n ' : ''}${bodyCode ? bodyCode + '\n\n ' : ''}const options = {\n method: "${method.toUpperCase()}",\n headers: {\n "Content-Type": "application/json"\n }${bodyCode ? ',\n body: JSON.stringify(payload)' : ''}\n };\n\n try {\n const response = await fetch(url, options);\n const data = await response.json();\n console.log(data);\n } catch (error) {\n console.error("Error:", error);\n }\n}\n\ncallApi();`;
}
function renderGoExample(path, method, operation, baseUrl) {
let url = `${baseUrl}${path}`;
const params = operation.parameters?.filter((p) => p.in === 'path') || [];
params.forEach((param) => {
const paramName = param.name;
url = url.replace(`{${paramName}}`, `${paramName}_value`);
});
const queryParams = operation.parameters?.filter((p) => p.in === 'query') || [];
let queryParamsCode = '';
if (queryParams.length > 0) {
queryParamsCode = `
// Add query parameters
q := req.URL.Query()
${queryParams.map((p) => `q.Add("${p.name}", "${p.name}_value")`).join('\n\t')}
req.URL.RawQuery = q.Encode()`;
}
let bodyCode = '';
let bodyImport = '';
if (method.toLowerCase() !== 'get' &&
operation.requestBody?.content?.['application/json']) {
const schema = operation.requestBody.content['application/json'].schema;
const exampleBody = generateExampleFromSchema(schema);
function convertToGoMap(obj, indent = '\t') {
if (obj === null)
return 'nil';
if (Array.isArray(obj)) {
if (obj.length === 0)
return '[]interface{}{}';
const items = obj
.map((item) => {
if (typeof item === 'object' && item !== null) {
return convertToGoMap(item, indent + '\t');
}
else if (typeof item === 'string') {
return `"${item}"`;
}
else {
return `${item}`;
}
})
.join(',\n' + indent + '\t');
return `[]interface{}{\n${indent}\t${items}\n${indent}}`;
}
if (typeof obj === 'object') {
const entries = Object.entries(obj)
.map(([key, value]) => {
if (typeof value === 'object' && value !== null) {
return `"${key}": ${convertToGoMap(value, indent + '\t')}`;
}
else if (typeof value === 'string') {
return `"${key}": "${value}"`;
}
else {
return `"${key}": ${value}`;
}
})
.join(',\n' + indent + '\t');
return `map[string]interface{}{\n${indent}\t${entries}\n${indent}}`;
}
return String(obj);
}
const goMapStr = convertToGoMap(exampleBody);
bodyImport = '\n\t"bytes"';
bodyCode = `
// Create request body
payload := ${goMapStr}
body, err := json.Marshal(payload)
if err != nil {
log.Fatalf("Error creating request body: %v", err)
}
req, err = http.NewRequest("${method.toUpperCase()}", "${url}", bytes.NewBuffer(body))`;
}
else {
bodyCode = `
req, err := http.NewRequest("${method.toUpperCase()}", "${url}", nil)`;
}
return `package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"${bodyImport}
)
func main() {${bodyCode}
if err != nil {
log.Fatalf("Error creating request: %v", err)
}${queryParamsCode}
// Add headers
req.Header.Set("Content-Type", "application/json")
// Send request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("Error sending request: %v", err)
}
defer resp.Body.Close()
// Read response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Error reading response: %v", err)
}
fmt.Println(string(body))
}`;
}
function getOperationId(path, method, operation) {
return (operation.operationId ||
`${method}-${path.replace(/[{}]/g, '').replace(/\//g, '-')}`);
}
const methodCounts = {
get: 0,
post: 0,
put: 0,
delete: 0,
patch: 0,
options: 0,
head: 0,
};
for (const tag in taggedPaths) {
const paths = taggedPaths[tag];
for (const path in paths) {
const methods = paths[path];
for (const method in methods) {
if (['get', 'post', 'put', 'delete', 'patch', 'options', 'head'].includes(method)) {
methodCounts[method]++;
}
}
}
}
function renderSchema(schema) {
if (!schema)
return '<span class="text-gray-500">null</span>';
function resolveRef(ref) {
if (!ref.startsWith('#/components/schemas/')) {
return { $ref: ref };
}
const schemaName = ref.replace('#/components/schemas/', '');
if (spec?.components?.schemas && spec.components.schemas[schemaName]) {
return spec.components.schemas[schemaName];
}
return { $ref: ref };
}
const clonedSchema = JSON.parse(JSON.stringify(schema));
function processSchema(obj) {
if (!obj || typeof obj !== 'object')
return obj;
if (obj.$ref) {
const resolved = resolveRef(obj.$ref);
return { ...processSchema(resolved), originalRef: obj.$ref };
}
if (obj.type === 'array' && obj.items) {
obj.items = processSchema(obj.items);
return obj;
}
if (obj.properties) {
Object.keys(obj.properties).forEach((key) => {
obj.properties[key] = processSchema(obj.properties[key]);
});
}
if (obj.additionalProperties &&
typeof obj.additionalProperties === 'object') {
obj.additionalProperties = processSchema(obj.additionalProperties);
}
return obj;
}
const processed = processSchema(clonedSchema);
function generateSchemaHTML(schema, level = 0, isArrayItem = false) {
if (!schema)
return '<span class="text-gray-500">null</span>';
const indent = ' '.repeat(level);
let html = '';
if (schema.type === 'object') {
if (schema.properties) {
html += '<div class="schema-object">';
if (!isArrayItem) {
html += `<div class="text-blue-600 font-semibold mb-1">Object</div>`;
}
html += '<ul class="pl-4 space-y-2">';
for (const propName in schema.properties) {
const prop = schema.properties[propName];
const required = schema.required && schema.required.includes(propName);
html += '<li>';
html += `<div><span class="font-mono font-medium">${propName}</span>`;
if (required) {
html +=
' <span class="text-red-500 text-xs font-semibold">required</span>';
}
html += `</div>`;
html += `<div class="text-sm">`;
if (prop.type) {
html += `<span class="text-green-600">${prop.type}</span>`;
if (prop.format) {
html += ` <span class="text-gray-500">(${prop.format})</span>`;
}
}
html += '</div>';
if (prop.description) {
html += `<div class="text-sm text-gray-600">${prop.description}</div>`;
}
if ((prop.type === 'object' && prop.properties) ||
(prop.type === 'array' && prop.items)) {
html += generateSchemaHTML(prop, level + 1);
}
html += '</li>';
}
html += '</ul></div>';
}
else {
html += '<div class="text-blue-600 font-semibold">Object</div>';
}
}
else if (schema.type === 'array') {
html += '<div class="schema-array">';
html += `<div class="text-blue-600 font-semibold mb-1">Array of:</div>`;
html += generateSchemaHTML(schema.items, level + 1, true);
html += '</div>';
}
else {
html += `<div class="text-green-600">${schema.type || 'unknown'}</div>`;
if (schema.format) {
html += ` <span class="text-gray-500">(${schema.format})</span>`;
}
if (schema.description) {
html += `<div class="text-sm text-gray-600">${schema.description}</div>`;
}
}
return html;
}
const jsonString = JSON.stringify(processed, null, 2);
return generateSchemaHTML(processed);
}
function renderExample(example) {
if (!example)
return 'null';
return JSON.stringify(example, null, 2);
}
return nunjucksEnv.render('content.njk', {
title,
description,
altDescription,
favicon,
logo: logoUrl,
logoAlt,
logoStyle,
logoContainerStyle,
logoContainerClass,
logoClickable,
cssVars,
cssVarsString,
customCss,
customJs,
customThemeCSS,
isDarkMode,
currentSpec: spec,
taggedPaths,
tagNameMapForTemplate,
methodColors,
specUrl,
baseUrl,
methodCounts,
getOperationId,
renderCodeExamples,
renderCurlExample,
renderPythonExample,
renderJavaScriptExample,
renderGoExample,
renderSchema,
renderExample,
specJsonString,
footer: options.footer,
});
}
//# sourceMappingURL=template.js.map