Skip to content

Commit

Permalink
Merge pull request #54 from expressots/feature/update-render-engine
Browse files Browse the repository at this point in the history
feat: update render engine en-pt
  • Loading branch information
rsaz committed Jul 23, 2024
2 parents d4cbb1b + ab37e07 commit eafeacc
Show file tree
Hide file tree
Showing 3 changed files with 349 additions and 98 deletions.
205 changes: 158 additions & 47 deletions docs/overview/render.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,79 +2,190 @@
sidebar_position: 17
---

# Render
# Render Engine

**[Express.js](https://expressjs.com/en/5x/api.html#res.render)** offers a `render` method to render a view and send the rendered HTML string to the client.
**[ExpressoTS](https://expresso-ts.com/)** enhances the web server capabilities of Express.js by providing a streamlined experience for rendering views. ExpressoTS supports various render engines out-of-the-box, including EJS, PUG, and Handlebars (HBS). This makes it easy for developers to start rendering views without needing additional configuration, as default settings are provided for each supported engine.

In ExpressoTS as we do support Express.js, we also support the `render` capability offered by the HTTP response object.
## Supported Render Engines

ExpressoTS implements a basic support for render engines in the `Application` class. At the moment the number of renders supported is limited to Handlebars.
ExpressoTS supports the following render engines:

We created the `RenderTemplateOptions` interface to provide a structure for the configuration options of future render engines.
Currently we just support a very limited number of options for Handlebars, but we will expand this in the future, not just the options but also the number of supported render engines.
- EJS
- PUG
- HBS (Handlebars)

## IHandlebars interface example
### Handlebars Configuration Options

```typescript
interface IHandlebars {
/**
* Specifies the extension name for the Handlebars templates.
*/
extName: string;

/**
* Specifies the path to the directory containing the Handlebars templates.
*/
viewPath: string;

/**
* Specifies the function for rendering Handlebars templates.
*/
engine: Engine;
export type HandlebarsOptions = {
viewEngine?: string; // The view engine to be used
viewsDir?: string; // The path to the views folder
partialsDir?: string; // The path to the partials folder
};
```

#### Default Handlebars configuration options

```typescript
{
viewEngine: "hbs",
viewsDir: <root>/views,
partialsDir: <root>/views/partials,
}
```

### Default Folder structure

type RenderTemplateOptions = IHandlebars;
Default folder structure for Handlebars:

```tree
src
views
|--partials
| |--partial.hbs
|--index.hbs
```

## How to use
All other engines follow the same structure, with the exception of the `partials` folder, which is specific to Handlebars.

### Handlebars File Example

```html
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>HBS Example</title>
</head>
<body>
<h1>Hello from HBS</h1>
<p>Render partial: {{> partial}}</p>
</body>
</html>
```

## Other Engine Configuration Options

### Pug Configuration Options

```typescript
export type PugOptions = {
viewEngine?: string;
viewsDir?: string;
};
```

#### Default Pug configuration options

```typescript
{
viewEngine: "pug",
viewsDir: <root>/views,
}
```

### EJS Configuration Options

```typescript
export type EjsOptions = {
viewsDir?: string;
viewEngine?: string;
serverOptions?: EjsOptionsServer;
};
```

#### Default EJS configuration options

```typescript
import { AppInstance, IHandlebars, ServerEnvironment } from "@expressots/core";
{
viewEngine: "ejs",
viewsDir: <root>/views,
serverOptions: {
cache: true,
compileDebug: false,
debug: false,
delimiter: "%",
strict: false,
},
}
```

## How to use

async function bootstrap() {
AppInstance.create(container);
Here's how you can set up ExpressoTS to use a render engine like HBS (handlebars) in your application:

// Setting handlebars as the view engine.
AppInstance.setEngine<IHandlebars>({
extName: "hbs",
viewPath: path.join(__dirname, "..", "views"),
engine: engine({ defaultLayout: "layout", extname: "hbs" }),
});
In the `app.provider` configuration provider, you can set the render engine:

AppInstance.listen(3000, ServerEnvironment.Development);
```typescript
export class App extends AppExpress {
private middleware: IMiddleware;
private provider: ProviderManager;

constructor() {
super();
this.middleware = container.get<IMiddleware>(Middleware);
this.provider = container.get(ProviderManager);
}

protected configureServices(): void {
// Set the render engine to HBS
this.setEngine(Engine.HBS);

this.middleware.setErrorHandler();
}

protected async postServerInitialization(): Promise<void> {
if (this.isDevelopment()) {
this.provider.get(Env).checkAll();
}
}

protected serverShutdown(): void {}
}
```

:::note
If you want to pass custom options to the render engine, you can do so by passing an object with the desired options to the `setEngine` method. For example, to set the views directory to a custom path, you can do the following:

bootstrap();
```typescript
this.setEngine<HBS>(Engine.HBS, { viewsDir: <<custom-path>> });
```

:::tip
For the code above to work, you need to install the **[express-handlebars](https://www.npmjs.com/package/express-handlebars)** package as well as having a folder structure similar to the one below.
:::

## Folder structure
### How To Render Views in ExpressoTS

```tree
src
|--views
| |--layouts
| | |--layout.hbs
| |--index.hbs
To render a view in ExpressoTS, you can use the `render` method provided by the `Response` object. Here's an example of how you can render a view in ExpressoTS:

```typescript
@Get("/")
root(@response() res: Response) {
res.render("index", { date: new Date(), name: "Random information" });
}
```

In the example above, the `render` method is called on the `Response` object, passing the name of the view to be rendered and an object with data to be passed to the view. The view engine will render the view with the provided data and return the rendered HTML to the client.

### Render Decorator

The `@Render` decorator can be used on controller methods to render views using the specified view engine. Here's an example of how you can use the `@Render` decorator to render a view in ExpressoTS:

#### Rendering passing the view and default data in the decorator

```typescript
@Get("/")
@Render("index", { date: new Date(), name: "Random information" })
root() {}
```

## Installing express-handlebars
#### Rendering passing only the view in the decorator

```bash
npm i express-handlebars
```typescript
@Get("/")
@Render("index")
root() {
return { date: new Date(), name: "Random information" };
}
```

---
Expand Down
38 changes: 34 additions & 4 deletions docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Config } from "@docusaurus/types";
import { themes } from "prism-react-renderer";
import axios from "axios";

const fetchVersion = async (): Promise<string> => {
const coreVersion = async (): Promise<string> => {
try {
const response = await axios.get(
"https://api.github.com/repos/expressots/expressots/releases"
Expand All @@ -16,6 +16,34 @@ const fetchVersion = async (): Promise<string> => {
}
};

const adapterVersion = async (): Promise<string> => {
try {
const response = await axios.get(
"https://api.github.com/repos/expressots/adapter-express/releases"
);

const latestRelease = response.data[0];
return latestRelease.tag_name;
} catch (error) {
console.error("Error fetching current version from GitHub:", error);
return "2.0.0"; // Fallback version
}
};

const cliVersion = async (): Promise<string> => {
try {
const response = await axios.get(
"https://api.github.com/repos/expressots/expressots-cli/releases"
);

const latestRelease = response.data[0];
return latestRelease.tag_name;
} catch (error) {
console.error("Error fetching current version from GitHub:", error);
return "2.0.0"; // Fallback version
}
};

const config: Config = {
title: "Expresso TS",
tagline: "A lightweight, fast and easy to use TypeScript framework",
Expand Down Expand Up @@ -80,7 +108,6 @@ const config: Config = {
indexName: "expresso-ts",
contextualSearch: true,
insights: true,
placeholder: "Search the docs (Press / to focus)",
appId: "3UANWN5EUQ",
},
navbar: {
Expand Down Expand Up @@ -175,10 +202,13 @@ const config: Config = {
};

export default async function asyncConfig(): Promise<Config> {
const version = await fetchVersion();
const core = await coreVersion();
const adapter = await adapterVersion();
const cli = await cliVersion();

config.themeConfig.announcementBar = {
id: "supportus",
content: `Current Version: ${version}`,
content: `@core v${core} / @adapter-express v${adapter} / @cli v${cli}`,
backgroundColor: "#111",
textColor: "#19CE59",
isCloseable: false,
Expand Down
Loading

0 comments on commit eafeacc

Please sign in to comment.