Skip to content

Commit

Permalink
added renderer option
Browse files Browse the repository at this point in the history
  • Loading branch information
redexp committed Mar 29, 2023
1 parent 99a4b75 commit 5f0848c
Show file tree
Hide file tree
Showing 9 changed files with 461 additions and 401 deletions.
8 changes: 4 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.idea/
node_modules/
tests/cache/
tests/views/cache/
.idea
node_modules
tests/cache
tests/views/cache
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ Full-featured template engine for express

[![Build Status](https://travis-ci.com/redexp/express-engine-jsx.svg?branch=master)](https://travis-ci.com/redexp/express-engine-jsx)

* [How it works](#how-it-works)
* [Usage](#usage)
* [API](#api)
* [engine](#engine)
* [options](#options)
* [require](#require)
* [convert](#convert)
* [run](#run)
* [Context](#context)
* [attr-map](#attr-map)
* [How to integrate to other engine](#how-to-integrate-to-other-engine)
* [Problem with more than one component in template root](#problem-with-more-than-one-component-in-template-root)

Example of `users.jsx` template file
```jsx harmony
const Layout = require('./layout');
Expand Down Expand Up @@ -155,7 +168,7 @@ It's a function which takes three arguments:

* `path` - path to jsx file
* `locals` - object with properties which will be local variables in jsx file
* `callback` - optional Node style callback which will receive html string as second argument
* `callback` - optional, Node style callback which will receive result of `options.renderer` as second argument

If you pass to `engine` only path and locals then it will return html.
```js
Expand All @@ -177,6 +190,7 @@ Object with optional properties:
* `DEV` - boolean, default `process.env.NODE_ENV !== 'production'`
* `sourceMap` - boolean, default `process.env.NODE_ENV !== 'production'`
* `doctype` - string which will be prepended to output html, default value is `"<!DOCTYPE html>\n"`
* `renderer` - function, default `ReactDOM.renderToStaticMarkup`
* `replace` - function which will take output html (without doctype), and it should return new html
* `addOnChange` - boolean, default `true`. Will add `onChnage={() => false}` to every `<input>` with `value` or `checked` attribute. Used to omit ReactDOM warning about `value` prop without `onChange` handler.
* `templatePath` - path to wrapper of compiled jsx, default value is `express-engine-jsx/template.jsx`. Undefined variable `BODY` will be replaced with your compiled jsx code.
Expand Down
34 changes: 22 additions & 12 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import {Stream} from "node:stream";
import {ScriptOptions} from "node:vm";
import {ParserOptions} from '@babel/parser/typings/babel-parser';
import {BabylonOptions} from 'babylon';
import {createElement, Context} from 'react';

declare function engine(path: string, params: object, cb: HtmlCallback): void;
declare function engine(path: string, cb: HtmlCallback): void;
declare function engine(path: string, params?: object): string;
declare function engine(path: string, params?: object): HtmlResult;

type HtmlCallback = (err: null|Error, html: string) => void;
type HtmlCallback = (err: null|Error, html: HtmlResult) => void;

declare namespace engine {
interface Options {
DEV?: boolean,
doctype?: string,
replace?: (html: string) => string,
renderer?: (node: ReturnType<typeof createElement>) => HtmlResult,
replace?: (html: HtmlResult, params: object) => HtmlResult,
templatePath?: string,
parserOptions?: import('@babel/parser/typings/babel-parser').ParserOptions,
parserOptions?: ParserOptions,
sourceMap?: boolean,
addOnChange?: boolean,
}
Expand All @@ -19,27 +26,30 @@ declare namespace engine {
path?: string,
sourceMap?: boolean,
addOnChange?: boolean,
parserOptions?: import('@babel/parser/typings/babel-parser').ParserOptions,
template?: false | string | Buffer | (({BODY}) => any),
parserOptions?: ParserOptions,
template?: false | JsxCode | (({BODY}) => any),
templatePath?: string,
templateOptions?: import('babylon').BabylonOptions,
templateOptions?: BabylonOptions,
}

interface RunOptions {
path?: string,
context?: object,
scriptOptions?: import('vm').ScriptOptions,
scriptOptions?: ScriptOptions,
}

export function setOptions(options: Options): void;

export function require(path: string, currentWorkingDir?: string): any;

export function convert(code: string|Buffer, options?: ConvertOptions): string|{code: string, map: null|object};
export function convert(code: JsxCode, options?: ConvertOptions): string|{code: string, map: null|object};

export function run(code: string|Buffer, options?: RunOptions): any;
export function run(code: JsxCode, options?: RunOptions): any;

export const Context: import('react').Context<{ locales: object, settings: object }>;
export const Context: Context<{locales: object, settings: object}>;
}

export = engine;
export = engine;

type JsxCode = string | Buffer;
type HtmlResult = string | Stream;
22 changes: 16 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const React = require('react');
const ReactDOM = require('react-dom/server');
const Combiner = require('combined-stream');
const options = require('./options');
const requireJSX = require('./require');
const convert = require('./convert');
Expand All @@ -21,8 +21,10 @@ function engine(path, params = {}, cb = null) {
settings: params.settings,
};

const {renderer, replace, doctype} = options;

try {
var html = ReactDOM.renderToStaticMarkup(
var html = renderer(
React.createElement(Context.Provider, {value: context},
React.createElement(Component, params)
)
Expand Down Expand Up @@ -62,12 +64,20 @@ function engine(path, params = {}, cb = null) {
}
}

if (options.replace) {
html = options.replace(html);
if (replace) {
html = replace(html, params);
}

if (options.doctype) {
html = options.doctype + html;
if (doctype) {
if (typeof html === 'string') {
html = doctype + html;
}
else {
const combiner = new Combiner();
combiner.append(doctype);
combiner.append(html);
html = combiner;
}
}

if (cb) {
Expand Down
2 changes: 2 additions & 0 deletions options.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const {resolve} = require('path');
const {renderToStaticMarkup} = require('react-dom/server');

const DEV = process.env.NODE_ENV !== 'production';

Expand All @@ -18,5 +19,6 @@ module.exports = {
addOnChange: true,
doctype: "<!DOCTYPE html>\n",
replace: null,
renderer: renderToStaticMarkup,
templatePath: resolve(__dirname, 'template.jsx'),
};
Loading

0 comments on commit 5f0848c

Please sign in to comment.