UNPKG

rapipdf

Version:

RapiPdf - Generate PDF from Open API spec

489 lines (457 loc) 18.3 kB
import marked from 'marked'; import { rowLinesTableLayout } from '@/table-layouts'; import { getMarkDownDef } from '@/markdown'; import { getTypeInfo, schemaInObjectNotation, objectToTree, objectToTableTree, } from '@/object-tree-gen'; // Info Def export function getInfoDef(spec, bookTitle, localize) { let content; if (spec.info) { let contactDef = []; let contactName; let contactEmail; let contactUrl; let termsOfService; if (spec.info.contact) { if (spec.info.contact.name) { contactName = { text: [{ text: `\n${localize.name}: `, style: ['b', 'small'] }, { text: spec.info.contact.name, style: ['small'] }] }; } if (spec.info.contact.email) { contactEmail = { text: [{ text: `\n${localize.email}: `, style: ['b', 'small'] }, { text: spec.info.contact.email, style: ['small'] }] }; } if (spec.info.contact.url) { contactUrl = { text: [{ text: `\n${localize.url}: `, style: ['b', 'small'] }, { text: spec.info.contact.url, style: ['small', 'blue'], link: spec.info.contact.url }] }; } if (spec.info.termsOfService) { termsOfService = { text: [{ text: `\n${localize.termsOfService}: `, style: ['b', 'small'] }, { text: spec.info.termsOfService, style: ['small', 'blue'], link: spec.info.termsOfService }] }; } contactDef = [ { text: localize.contact, style: ['p', 'b', 'topMargin3'] }, { text: [ contactName, contactEmail, contactUrl, termsOfService, ], }, ]; } let specInfDescrMarkDef; if (spec.info.description) { const tokens = marked.lexer(spec.info.description); specInfDescrMarkDef = { stack: getMarkDownDef(tokens), style: ['topMargin3'], }; } else { specInfDescrMarkDef = ''; } content = [ { text: bookTitle || localize.apiReference, style: ['h2', 'primary', 'right', 'b', 'topMargin1'] }, (spec.info.title ? { text: spec.info.title, style: ['title', 'right'] } : ''), (spec.info.version ? { text: `${localize.apiVersion}: ${spec.info.version}`, style: ['p', 'b', 'right', 'alternate'] } : ''), specInfDescrMarkDef, ...contactDef, { text: '', pageBreak: 'after' }, ]; } else { content = [ { text: bookTitle || localize.apiReference, style: ['h1', 'bold', 'primary', 'right', 'topMargin1'] }, { text: '', pageBreak: 'after' }, ]; } return content; } // Security Def export function getSecurityDef(spec, localize) { const content = []; if (spec.securitySchemes) { content.push({ text: localize.securityAndAuthentication, style: ['h3', 'b', 'primary', 'right', 'topMargin3'] }); content.push({ text: localize.securitySchemes, style: ['b', 'tableMargin'] }); const tableContent = [ [{ text: localize.key, style: ['small', 'b'] }, { text: localize.type, style: ['small', 'b'] }, { text: localize.description, style: ['small', 'b'] }], ]; for (const key in spec.securitySchemes) { tableContent.push([ key, spec.securitySchemes[key].type + (spec.securitySchemes[key].scheme ? (`, ${spec.securitySchemes[key].scheme}`) : '') + (spec.securitySchemes[key].bearerFormat ? (`, ${spec.securitySchemes[key].bearerFormat}`) : ''), spec.securitySchemes[key].description ? spec.securitySchemes[key].description : '', ]); } content.push({ table: { headerRows: 1, body: tableContent, }, layout: rowLinesTableLayout, style: 'tableMargin', pageBreak: 'after', }); } return content; } // Parameter Table function getParameterTableDef(parameters, paramType, localize, includeExample = false) { // let filteredParams= parameters ? parameters.filter(param => param.in === paramType):[]; if (parameters === undefined || parameters.length === 0) { return; } const tableContent = [ [ { text: localize.name, style: ['sub', 'b', 'alternate'] }, { text: localize.type, style: ['sub', 'b', 'alternate'] }, { text: includeExample ? localize.example : '', style: ['sub', 'b', 'alternate'] }, { text: localize.description, style: ['sub', 'b', 'alternate'] }, ], ]; if (paramType === 'FORM DATA') { for (const paramName in parameters) { const param = parameters[paramName]; let { type } = param; const format = param.format === 'binary' ? '(binary)' : ''; if (type === 'array') { type = `array of ${param.items.type}`; } tableContent.push([ { text: paramName, style: ['small', 'mono'] }, { text: type + format, style: ['small', 'mono'] }, { text: includeExample ? (param.example ? param.example : (param.examples && param.examples[0] ? param.examples[0] : '')) : '', style: ['small'], margin: [0, 2, 0, 0] }, { text: param.description, style: ['small'], margin: [0, 2, 0, 0] }, ]); } } else { parameters.map((param) => { const paramSchema = getTypeInfo(param.schema); tableContent.push([ { text: [ { text: param.required ? '*' : '', style: ['small', 'b', 'red', 'mono'] }, { text: param.name, style: ['small', 'mono'] }, (paramSchema.deprecated ? { text: `\n${localize.deprecated}`, style: ['small', 'red', 'b'] } : ''), ], }, { stack: [ { text: `${paramSchema.type === 'array' ? paramSchema.arrayType : (paramSchema.format ? paramSchema.format : paramSchema.type)}`, style: ['small', 'mono'] }, (paramSchema.constrain ? { text: paramSchema.constrain, style: ['small', 'gray'] } : ''), (paramSchema.allowedValues ? { text: [ { text: `${localize.allowed}: `, style: ['b', 'sub'] }, { text: paramSchema.allowedValues, style: ['small', 'lightGray'] }, ], } : '' ), (paramSchema.pattern ? { text: `${localize.pattern}: ${paramSchema.pattern}`, style: ['small', 'gray'] } : ''), ], }, { text: includeExample ? (param.example ? param.example : (param.examples && param.examples[0] ? param.examples[0] : '')) : '', style: ['small'], margin: [0, 2, 0, 0] }, { text: param.description, style: ['small'], margin: [0, 2, 0, 0] }, ]); }); } return [ { text: `${paramType} ${localize.parameters}`.toUpperCase(), style: ['small', 'b'], margin: [0, 10, 0, 0] }, { table: { headerRows: 1, dontBreakRows: true, widths: ['auto', 'auto', includeExample ? 'auto' : 0, '*'], body: tableContent, }, layout: rowLinesTableLayout, style: 'tableMargin', }, ]; } // Request Body Def function getRequestBodyDef(requestBody, schemaStyle, localize) { if (!requestBody) { return; } const content = []; let formParamDef; for (const contentType in requestBody.content) { const contentTypeObj = requestBody.content[contentType]; const requestBodyDef = [ { text: `${localize.requestBody} - ${contentType}`, margin: [0, 10, 0, 0], style: ['small', 'b'] }, ]; if ((contentType.includes('form') || contentType.includes('multipart-form')) && contentTypeObj.schema) { formParamDef = getParameterTableDef(contentTypeObj.schema.properties, 'FORM DATA', localize); content.push(formParamDef); } else if (contentType.includes('json') || contentType.includes('xml')) { let origSchema = requestBody.content[contentType].schema; if (origSchema) { origSchema = JSON.parse(JSON.stringify(origSchema)); const schemaInObjectNotaion = schemaInObjectNotation(origSchema); if (schemaStyle === 'object') { let treeDef; if (schemaInObjectNotaion['::type'] && schemaInObjectNotaion['::type'] === 'array') { treeDef = objectToTree(schemaInObjectNotaion['::props'], localize, 'array'); } else { treeDef = objectToTree(schemaInObjectNotaion, localize); } requestBodyDef.push(treeDef); } else { // if Schema Style is Tree let schemaTableTreeDef; if (schemaInObjectNotaion['::type'] && schemaInObjectNotaion['::type'] === 'array') { schemaTableTreeDef = objectToTableTree(schemaInObjectNotaion['::prop'], localize, 'array'); } else { schemaTableTreeDef = objectToTableTree(schemaInObjectNotaion, localize); } if (schemaTableTreeDef && schemaTableTreeDef.length > 0 && Array.isArray(schemaTableTreeDef[0]) && schemaTableTreeDef[0].length > 0) { schemaTableTreeDef.unshift([ { text: localize.name, style: ['sub', 'b', 'alternate'] }, { text: localize.type, style: ['sub', 'b', 'alternate'] }, { text: localize.description, style: ['sub', 'b', 'alternate'] }, ]); requestBodyDef.push({ table: { headerRows: 1, body: schemaTableTreeDef, }, layout: rowLinesTableLayout, margin: [0, 3, 0, 0], }); } } } content.push(requestBodyDef); } } return content; } // Response Def function getResponseDef(responses, schemaStyle, localize) { const respDef = []; for (const statusCode in responses) { const allResponseDefs = []; for (const contentType in responses[statusCode].content) { const responseDef = [ { text: `${localize.responseModel} - ${contentType}`, margin: [10, 10, 0, 0], style: ['small', 'b'] }, ]; let origSchema = responses[statusCode].content[contentType].schema; if (origSchema) { origSchema = JSON.parse(JSON.stringify(origSchema)); const schemaInObjectNotaion = schemaInObjectNotation(origSchema); if (schemaStyle === 'object') { let schemaTreeDef; if (schemaInObjectNotaion['::type'] && schemaInObjectNotaion['::type'] === 'array') { schemaTreeDef = objectToTree(schemaInObjectNotaion['::props'], localize, 'array'); } else { schemaTreeDef = objectToTree(schemaInObjectNotaion, localize); } if (Array.isArray(schemaTreeDef) && schemaTreeDef.length > 0) { schemaTreeDef[0].margin = [10, 5, 0, 0]; responseDef.push(schemaTreeDef); } } else { // If Schema style is Table-Tree let schemaTableTreeDef; let rootObjectType; if (schemaInObjectNotaion['::type'] && schemaInObjectNotaion['::type'] === 'array') { schemaTableTreeDef = objectToTableTree(schemaInObjectNotaion['::props'], localize); rootObjectType = [{ text: 'ARRAY OF OBJECT WITH BELOW STRUCTURE', style: ['sub', 'b', 'alternate'], colSpan: 3 }]; } else { schemaTableTreeDef = objectToTableTree(schemaInObjectNotaion, localize); rootObjectType = [{ text: 'OBJECT WITH BELOW STRUCTURE', style: ['sub', 'b', 'alternate'], colSpan: 3 }]; } if (schemaTableTreeDef && schemaTableTreeDef.length > 0 && Array.isArray(schemaTableTreeDef[0]) && schemaTableTreeDef[0].length > 0) { schemaTableTreeDef.unshift(rootObjectType); schemaTableTreeDef.unshift([ { text: localize.name, style: ['sub', 'b', 'alternate'] }, { text: localize.type, style: ['sub', 'b', 'alternate'] }, { text: localize.description, style: ['sub', 'b', 'alternate'] }, ]); responseDef.push({ table: { headerRows: 1, body: schemaTableTreeDef, dontBreakRows: true, }, layout: rowLinesTableLayout, margin: [10, 3, 0, 0], }); } } } allResponseDefs.push(responseDef); } respDef.push({ text: [ { text: `${localize.statusCode} - ${statusCode}: `, style: ['small', 'b'] }, { text: responses[statusCode].description, style: ['small'] }, ], margin: [0, 10, 0, 0], }); if (allResponseDefs.length > 0) { respDef.push(allResponseDefs); } } return respDef; } // API details def export function getApiDef(spec, filterPath, schemaStyle, localize, includeExample) { const content = [{ text: localize.api, style: ['h2', 'b'] }]; let tagSeq = 0; spec.tags.map((tag) => { const operationContent = []; let pathSeq = 0; for (let j = 0; j < tag.paths.length; j++) { const path = tag.paths[j]; if (filterPath.trim() !== '') { if (path.path.includes(filterPath) === false) { continue; } } pathSeq += 1; operationContent.push({ text: `${tagSeq + 1}.${pathSeq} ${path.method.toUpperCase()} ${path.path}`, style: ['topMargin3', 'mono', 'p', 'primary', 'b'], tocItem: true, tocStyle: ['small', 'blue', 'mono'], tocNumberStyle: ['small', 'blue', 'mono'], }); operationContent.push({ text: '', style: ['topMarginRegular'] }); let pathSummaryMarkDef; let pathDescrMarkDef; let tokens; if (path.summary) { tokens = marked.lexer(path.summary); pathSummaryMarkDef = { stack: getMarkDownDef(tokens), style: ['primary', 'b'], }; operationContent.push(pathSummaryMarkDef); } if (path.description && path.description.trim() !== path.summary.trim()) { tokens = marked.lexer(path.description); pathDescrMarkDef = { stack: getMarkDownDef(tokens), }; operationContent.push(pathDescrMarkDef); } // Generate Request Defs const requestSetDef = []; const pathParams = path.parameters ? path.parameters.filter((param) => param.in === 'path') : null; const queryParams = path.parameters ? path.parameters.filter((param) => param.in === 'query') : null; const headerParams = path.parameters ? path.parameters.filter((param) => param.in === 'header') : null; const cookieParams = path.parameters ? path.parameters.filter((param) => param.in === 'cookie') : null; const pathParamTableDef = getParameterTableDef(pathParams, 'path', localize, includeExample); const queryParamTableDef = getParameterTableDef(queryParams, 'query', localize, includeExample); const requestBodyTableDefs = getRequestBodyDef(path.requestBody, schemaStyle, localize, includeExample); const headerParamTableDef = getParameterTableDef(headerParams, 'header', localize, includeExample); const cookieParamTableDef = getParameterTableDef(cookieParams, 'cookie', localize, includeExample); operationContent.push({ text: localize.request, style: ['p', 'b', 'alternate'], margin: [0, 10, 0, 0] }); if (pathParamTableDef || queryParamTableDef || headerParamTableDef || cookieParamTableDef || requestBodyTableDefs) { if (pathParamTableDef) { requestSetDef.push(pathParamTableDef); } if (queryParamTableDef) { requestSetDef.push(queryParamTableDef); } if (requestBodyTableDefs) { requestBodyTableDefs.map((v) => { requestSetDef.push(v); }); } if (headerParamTableDef) { requestSetDef.push(headerParamTableDef); } if (cookieParamTableDef) { requestSetDef.push(cookieParamTableDef); } } else { requestSetDef.push({ text: localize.noRequestParameters, style: ['small', 'gray'], margin: [0, 5, 0, 0] }); } if (requestSetDef && requestSetDef.length > 0) { operationContent.push({ stack: requestSetDef, margin: [10, 0, 0, 0], }); } // Generate Response Defs operationContent.push({ text: localize.response, style: ['p', 'b', 'alternate'], margin: [0, 10, 0, 0] }); const respDef = getResponseDef(path.responses, schemaStyle, localize); if (respDef && respDef.length > 0) { operationContent.push({ stack: respDef, margin: [10, 5, 0, 5], }); } // End of Operation - Line operationContent.push({ canvas: [{ type: 'line', x1: 0, y1: 5, x2: 595 - 2 * 35, y2: 5, lineWidth: 0.5, lineColor: '#cccccc', }], }); } if (pathSeq > 0) { tagSeq += 1; let tagDescrMarkDef; let tokens; if (tag.description) { tokens = marked.lexer(tag.description); tagDescrMarkDef = { stack: getMarkDownDef(tokens), style: ['topMarginRegular'], }; } else { tagDescrMarkDef = { text: '' }; } content.push( { text: `${tagSeq}. ${tag.name.toUpperCase()}`, style: ['h2', 'b', 'primary', 'tableMargin'], tocItem: true, tocStyle: ['small', 'b'], tocMargin: [0, 10, 0, 0], }, tagDescrMarkDef, operationContent, { text: '', pageBreak: 'after' }, ); } }); return content; } // API List Def export function getApiListDef(spec, sectionHeading, localize) { const content = [{ text: sectionHeading, style: ['h3', 'b'], pageBreak: 'none' }]; spec.tags.map((tag, i) => { const tableContent = [ [{ text: localize.method, style: ['small', 'b'] }, { text: localize.api, style: ['small', 'b'] }], ]; tag.paths.map((path) => { tableContent.push([ { text: path.method, style: ['small', 'mono', 'right'] }, { margin: [0, 0, 0, 2], stack: [ { text: path.path, style: ['small', 'mono'] }, { text: path.summary, style: ['small', 'gray'] }, ], }, ]); }); content.push( { text: tag.name, style: ['h6', 'b', 'primary', 'tableMargin'], pageBreak: i === 0 ? 'none' : 'after' }, { text: tag.description, style: ['p'] }, { table: { headerRows: 1, dontBreakRows: true, widths: ['auto', '*'], body: tableContent, }, layout: rowLinesTableLayout, style: 'tableMargin', }, ); }); return content; }