Skip to content

Commit

Permalink
refactor(filenames): rename main files to make it expose an api in th…
Browse files Browse the repository at this point in the history
…e future

index.js is now called swagger-markdown.js, convert.js jhas been renamed to index.js. the references
to a binary executable remains the same

BREAKING CHANGE: the main executable file has been renamed, index.js is now swagger-markdown.js. no
changes if used via npx (npx swagger-markdown). may not work with browser implementations tho
  • Loading branch information
syroegkin committed Dec 26, 2022
1 parent 533d8b0 commit 44fc7fc
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 133 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "2.0.0-beta.7",
"description": "Create markdown API documentation from swagger file",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"test": "npm run test:app && npm run test:lint && npm run test:markdown",
"test:app": "jest --detectOpenHandles --forceExit",
Expand All @@ -18,7 +19,7 @@
"prepare": "husky install"
},
"bin": {
"swagger-markdown": "dist/index.js"
"swagger-markdown": "dist/swagger-markdown.js"
},
"config": {
"commitizen": {
Expand Down
2 changes: 1 addition & 1 deletion scripts/make-examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fs.readdir(directory, (err, files) => {
if (!filename.match(/\.yaml$/)) return;
console.log(`Processing ${filename}`);
try {
execSync(`node dist/index.js -i examples/${filename}`);
execSync(`node dist/swagger-markdown.js -i examples/${filename}`);
console.log('Done\n');
} catch (e) {
console.log(e);
Expand Down
94 changes: 0 additions & 94 deletions src/convert.ts

This file was deleted.

128 changes: 92 additions & 36 deletions src/index.ts
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,38 +1,94 @@
import { ArgumentParser } from 'argparse';
import { transformFile } from './convert';
import { Options } from './types';
import packageInfo = require('../package.json');

const parser = new ArgumentParser({
description: packageInfo.name,
add_help: true,
});

parser.add_argument('-v', '--version', {
action: 'version',
version: packageInfo.version,
});
parser.add_argument('-i', '--input', {
required: true,
help: 'Path to the swagger yaml file',
metavar: '',
dest: 'input',
});
parser.add_argument('-o', '--output', {
help: 'Path to the resulting md file',
metavar: '',
dest: 'output',
});
parser.add_argument('--skip-info', {
action: 'store_true',
help: 'Skip the title, description, version etc, whatever is in the info block.',
dest: 'skipInfo',
});
const args: Options = parser.parse_args();

if (args.input) {
if (!args.output) {
args.output = args.input.replace(/(yaml|yml|json)$/i, 'md');
import SwaggerParser from '@apidevtools/swagger-parser';
import fs from 'fs';
import markdownlint from 'markdownlint';
import markdownlintRuleHelpers from 'markdownlint-rule-helpers';
import { AllSwaggerDocumentVersions, Options } from './types';
import { isV2Document, isV31Document, isV3Document } from './lib/detectDocumentVersion';
import { transformSwaggerV2 } from './transformers/documentV2';

// eslint-disable-next-line @typescript-eslint/no-var-requires
const markdownlintConfig = require('../.markdownlint.json');

/**
* Replace all $refs with their values,
* except model definitions as these have their own section in the result md document
*
* @export
* @param {AllSwaggerDocumentVersions} node
* @param {SwaggerParser.$Refs} [$refs]
* @return {*} {AllSwaggerDocumentVersions}
*/
export function partiallyDereference(
node: AllSwaggerDocumentVersions,
$refs?: SwaggerParser.$Refs,
): AllSwaggerDocumentVersions {
if (typeof node !== 'object') return node;
const obj = {} as AllSwaggerDocumentVersions;
const entries = Object.entries(node);
for (let i = 0; i < entries.length; i++) {
const [key, value] = entries[i];
if (Array.isArray(value)) {
obj[key] = value.map((item) => partiallyDereference(item, $refs));
} else if (key === '$ref' && !value.startsWith('#/definitions/')) {
return partiallyDereference($refs.get(value), $refs);
} else {
obj[key] = partiallyDereference(value, $refs);
}
}
return obj;
}

/**
* Check version of the document,
* run appropriate processor and beautify the markdown after processing.
*
* @export
* @param {AllSwaggerDocumentVersions} inputDoc
* @param {Options} options
* @return {*} {string}
*/
export function transfromSwagger(inputDoc: AllSwaggerDocumentVersions, options: Options): string {
let plainDocument = '';

if (isV2Document(inputDoc)) {
plainDocument = transformSwaggerV2(inputDoc, options);
} else if (isV3Document(inputDoc)) {
throw new Error('OpenAPI V3 is not yet supported');
} else if (isV31Document(inputDoc)) {
throw new Error('OpenAPI V3.1 is not yet supported');
} else {
throw new Error('Can not detect version ot this version in not supported');
}

// Fix markdown issues
const fixOptions = {
resultVersion: 3,
strings: { plainDocument },
config: markdownlintConfig,
};
const fixResults = markdownlint.sync(fixOptions);
const fixes = fixResults.plainDocument.filter((error) => error.fixInfo);
if (fixes.length > 0) {
return markdownlintRuleHelpers.applyFixes(plainDocument, fixes);
}
transformFile(args).catch((err) => console.error(err));

return plainDocument;
}

/**
* @export
* @param {Options} options
* @return {*} {Promise<string>}
*/
export async function transformFile(options: Options): Promise<string> {
const swaggerParser = new SwaggerParser();
const $refs: SwaggerParser.$Refs = await swaggerParser.resolve(options.input);
const dereferencedDocument = partiallyDereference(swaggerParser.api, $refs);
const markdown = transfromSwagger(dereferencedDocument, options);

if (options.output) {
fs.writeFileSync(options.output, markdown);
}

return markdown;
}
38 changes: 38 additions & 0 deletions src/swagger-markdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ArgumentParser } from 'argparse';
import { transformFile } from './index';
import { Options } from './types';
import packageInfo = require('../package.json');

const parser = new ArgumentParser({
description: packageInfo.name,
add_help: true,
});

parser.add_argument('-v', '--version', {
action: 'version',
version: packageInfo.version,
});
parser.add_argument('-i', '--input', {
required: true,
help: 'Path to the swagger yaml file',
metavar: '',
dest: 'input',
});
parser.add_argument('-o', '--output', {
help: 'Path to the resulting md file',
metavar: '',
dest: 'output',
});
parser.add_argument('--skip-info', {
action: 'store_true',
help: 'Skip the title, description, version etc, whatever is in the info block.',
dest: 'skipInfo',
});
const args: Options = parser.parse_args();

if (args.input) {
if (!args.output) {
args.output = args.input.replace(/(yaml|yml|json)$/i, 'md');
}
transformFile(args).catch((err) => console.error(err));
}
2 changes: 1 addition & 1 deletion tests/convert.spec.ts → tests/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import SwaggerParser from '@apidevtools/swagger-parser';
import { expect } from 'chai';
import fs from 'fs';
import { transformFile, partiallyDereference } from '../src/convert';
import { transformFile, partiallyDereference } from '../src/index';
import { AllSwaggerDocumentVersions } from '../src/types';

describe('Integration test examples', () => {
Expand Down

0 comments on commit 44fc7fc

Please sign in to comment.