Skip to content

Commit

Permalink
handlebars partials and helpers support
Browse files Browse the repository at this point in the history
  • Loading branch information
carlosrivera committed Mar 6, 2021
1 parent 05ad6e1 commit 0f8ae2a
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 2 deletions.
Empty file.
3 changes: 3 additions & 0 deletions example/templates/custom/helpers/loud.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
exports.default = function (text) {
return text.toUpperCase()
}
1 change: 1 addition & 0 deletions example/templates/custom/partials/quote.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
>{{text}}
1 change: 1 addition & 0 deletions example/templates/custom/partials/sub-folder/bold.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**{{text}}**
11 changes: 11 additions & 0 deletions example/templates/custom/path.hdb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
id: {{method.operationId}}
title: {{method.summary}}
---

## This will call a partial template to create the quote
{{>quote text="Hello, World!"}}

Part of this text will be {{>bold text="bold"}}

{{loud "This text will uppercased using a helper"}}
Empty file.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@synx-ai/oas3-mdx",
"version": "0.3.12",
"version": "0.4.1",
"description": "Convert OpenAPI spec to Markdown files.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
40 changes: 39 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ For the parser, while `mdx` or `markdown` are suggested, you can use anything su

For every [**operation**](https://swagger.io/docs/specification/paths-and-operations/) in `paths`, object with all references resolved will be passed to `templates/path.hdb`, please refer to default template for an example in how to use it.

Please note that before saving, prettify will be executed to format the output, you can disable it using the `<!-- prettier-ignore-start -->` tag, exmaple:
Please note that before saving, prettify will be executed to format the output, you can disable it using the `<!-- prettier-ignore-start -->` tag, example:

```html
<!-- prettier-ignore-start -->
Expand All @@ -122,6 +122,44 @@ Please note that before saving, prettify will be executed to format the output,

<!-- prettier-ignore-end -->
```

### Using partials

In your `templatesPath` create a `dir` called `partials` every single file with `.hdb` extension within its subdirs will be loaded as partial, using the filename as partial name. Example:

A file named `partials/quote.hdb` with the following code, will create a `quote` partial.

```
>{{text}}
```

This partial can be used in your templates as follows:

```markdown
{{>quote "This text will be quoted."}}
```

### Using helpers

In your `templatesPath` create a `dir` called `helpers` every single file with `.js` extension within its subdirs will be loaded as a helper, using the filename as the helper name. Example:

A file named `partials/loud.js` with the following code, will create a `load` helper.

```javascript
// the script should export an anonymous function in order to execute
// you can use many parameters as needed
exports.default = function (text) {
return text.toUpperCase()
}
```

This helper can be used in your templates as follows:

```markdown
{{loud "This text will be uppercased."}}
```


## Troubleshooting
- Most common errors happens due a malformed file, to validate and lint your spec for possible errors check [Speccy](https://github.com/wework/speccy).
- If your specification has multiple paths which map to the same OpenAPI path, you can should set `"x-hasEquivalentPaths": true,` on the root object, example:
Expand Down
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as OpenAPISnippet from "openapi-snippet";

import * as prettier from "prettier";
import bundler from "./bundler";
import loaders from "./loaders";

/**
* Helper function to render a block of code
Expand Down Expand Up @@ -98,6 +99,9 @@ const convert = (specFile: string, options: Optional = {}): Promise<void> => {
// ToDo: delete existing path
}

loaders.loadHelpers(path.resolve(process.cwd(), path.join(templatesPath, "helpers")));
loaders.loadPartials(path.resolve(process.cwd(), path.join(templatesPath, "partials")));

Handlebars.registerHelper("codeSnippet", (content: string, lang: string, title: string) => {
// render code block
return codeBlock(content, lang, title);
Expand Down
51 changes: 51 additions & 0 deletions src/loaders.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"use strict";

import * as fs from "fs";
import * as path from "path";
import * as Handlebars from "handlebars";

const walkSync = (partialsPath: string, filelist: string[] = []): string[] => {
fs.readdirSync(partialsPath).forEach((file) => {
filelist = fs.statSync(path.join(partialsPath, file)).isDirectory()
? walkSync(path.join(partialsPath, file), filelist)
: filelist.concat(path.join(partialsPath, file));
});
return filelist;
};

const loaders = {
loadPartials: (partialsPath: string) => {
if (fs.existsSync(partialsPath)) {
const filelist = walkSync(partialsPath);
if (filelist.length > 0) {
Object.values(filelist).forEach((filename) => {
const matches = /^([^.]+).hbs$/.exec(path.basename(filename));
if (!matches) {
return;
}
const name = matches[1];
const template = fs.readFileSync(filename, "utf8");
Handlebars.registerPartial(name, template);
});
}
}
},
loadHelpers: (helpersPath: string) => {
if (fs.existsSync(helpersPath)) {
const filelist = walkSync(helpersPath);
if (filelist.length > 0) {
Object.values(filelist).forEach((filename) => {
const matches = /^([^.]+).js$/.exec(path.basename(filename));
if (!matches) {
return;
}
const name = matches[1];
const helper = require(filename).default;
Handlebars.registerHelper(name, helper);
});
}
}
},
};

export default loaders;
6 changes: 6 additions & 0 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const fileThatExistsInAnotherFormat = "./readme.md";

const templatesThatExists = "./example/templates/mdx";
const templatesThatNotExists = "./example/templates/jsx";
const templatesThatExistsCustomized = "./example/templates/custom";

const urlThatExists = "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore.yaml";
const urlThatNotExists = "https://github.com/synx-ai/oas3-mdx/blob/master/404";
Expand All @@ -23,6 +24,11 @@ describe("convert()", () => {
return expect(convert(fileThatExists, { outPath: "./build", templatesPath: templatesThatExists, prettierParser: "markdown" })).resolves.toBeUndefined();
});

// this will test a custom template options, also will test another parser and the use of handlebar partials
it("should execute from file", () => {
return expect(convert(fileThatExists, { outPath: "./build/custom", templatesPath: templatesThatExistsCustomized })).resolves.toBeUndefined();
});

// this will test a failed attempt to execute
it("should reject from wrong template dir", () => {
return expect(convert(fileThatExists, { outPath: "./build", templatesPath: templatesThatNotExists })).rejects.toBe("Can not find templates path");
Expand Down

0 comments on commit 0f8ae2a

Please sign in to comment.