Skip to content

Commit

Permalink
feat: tansform jsx to html
Browse files Browse the repository at this point in the history
  • Loading branch information
chenjun1011 committed Aug 29, 2019
1 parent 4dac008 commit f50cc43
Show file tree
Hide file tree
Showing 6 changed files with 572 additions and 43 deletions.
107 changes: 107 additions & 0 deletions packages/babel-plugin-transform-jsx-to-html/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# babel-plugin-transform-jsx-to-html
> Transform jsx to html string for better ssr performance.
## Installation

```sh
npm install --save-dev babel-plugin-transform-jsx-to-html
```

## Usage

### Via `.babelrc`

**.babelrc**

```json
{
"plugins": [
"babel-plugin-transform-jsx-to-html",
"babel/plugin-transform-react-jsx"
]
}
```

## Example

### basic example

Your `component.js` that contains this code:

```js
import { createElement, Component } from 'rax';

class App extends Component {
render() {
return <div className="header" />
}
}
```

Will be transpiled like this:

```js
import { createElement, Component } from 'rax';

class App extends Component {
render() {
return [{
__html: '<div class="header" />'
}];
}
}
```

These pre transpiled html can be used in server renderer, like [rax-server-renderer](https://github.com/alibaba/rax/tree/master/packages/rax-server-renderer)

### more examples

input

```jsx
<div>
<View />
</div>
```

output

```js
[{
__html: "<div>"
},
createElement(View, null),
{
__html: "</div>"
}]
```

input

```jsx
<div className="container" style={style} onClick={onClick}>
<div>a {props.index}</div>
</div>
```

output

```js
[{
__html: "<div class=\\"container\\""
}, {
__attrs: {
style: style,
onClick: onClick
}
}, {
__html: ">"
}, [{
__html: "<div>"
}, "a ", props.index, {
__html: "</div>"
}], {
__html: "</div>"
}]

```
27 changes: 27 additions & 0 deletions packages/babel-plugin-transform-jsx-to-html/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "babel-plugin-transform-jsx-to-html",
"version": "0.1.0",
"description": "Transform JSX to Html.",
"license": "BSD-3-Clause",
"main": "lib/index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/alibaba/rax.git"
},
"bugs": {
"url": "https://github.com/alibaba/rax/issues"
},
"homepage": "https://github.com/alibaba/rax#readme",
"engines": {
"npm": ">=3.0.0"
},
"devDependencies": {
"@babel/core": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/preset-react": "^7.0.0"
},
"dependencies": {
"@babel/types": "^7.5.5",
"esutils": "^2.0.3"
}
}
160 changes: 160 additions & 0 deletions packages/babel-plugin-transform-jsx-to-html/src/__tests__/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
const jsxToHtmlPlugin = require('../index');
const { transformSync } = require('@babel/core');

function getTransfromCode(code, opts) {
return transformSync(code, {
filename: './',
presets: [
['@babel/preset-env', {
'loose': true,
'modules': false
}],
require.resolve('@babel/preset-react'),
],
plugins: [
jsxToHtmlPlugin,
['@babel/plugin-transform-react-jsx', {
pragma: 'createElement'
}],
],
}).code;
}

describe('transform jsx to html', () => {
it('tansform with pure html tags', () => {
expect(getTransfromCode(`
<div>
<div>a</div>
<div>b</div>
</div>
`)).toBe(`[{
__html: "<div>"
}, [{
__html: "<div>"
}, "a", {
__html: "</div>"
}], [{
__html: "<div>"
}, "b", {
__html: "</div>"
}], {
__html: "</div>"
}];`);
});

it('tansform with component', () => {
expect(getTransfromCode(`
<div>
<View />
</div>
`)).toBe(`[{
__html: "<div>"
}, createElement(View, null), {
__html: "</div>"
}];`);
});

it('tansform component with children', () => {
expect(getTransfromCode(`
<View>
<div>a</div>
<div>b</div>
</View>
`)).toBe(`createElement(View, null, [{
__html: "<div>"
}, "a", {
__html: "</div>"
}], [{
__html: "<div>"
}, "b", {
__html: "</div>"
}]);`);
});

it('tansform with props', () => {
expect(getTransfromCode(`
<div className="container" style={style} onClick={onClick}>
<div>a {props.index}</div>
<div>b {props.index}</div>
</div>
`)).toBe(`[{
__html: "<div class=\\"container\\""
}, {
__attrs: {
style: style,
onClick: onClick
}
}, {
__html: ">"
}, [{
__html: "<div>"
}, "a ", props.index, {
__html: "</div>"
}], [{
__html: "<div>"
}, "b ", props.index, {
__html: "</div>"
}], {
__html: "</div>"
}];`);
});

it('tansform with slot', () => {
expect(getTransfromCode(`
const slot = <div>slot</div>;
<div className="container">
{slot}
</div>
`)).toBe(`var slot = [{
__html: "<div>"
}, "slot", {
__html: "</div>"
}];
[{
__html: "<div class=\\"container\\">"
}, slot, {
__html: "</div>"
}];`);
});

it('tansform with es5 component', () => {
expect(getTransfromCode(`
const slot = createElement('div', null, 'slot');
<div className="container">
{slot}
</div>
`)).toBe(`var slot = createElement('div', null, 'slot');
[{
__html: "<div class=\\"container\\">"
}, slot, {
__html: "</div>"
}];`);
});

it('tansform with innnerHtml', () => {
expect(getTransfromCode(`
<div dangerouslySetInnerHTML={{__html: "<div>a</div>"}} />
`)).toBe(`[{
__html: "<div>"
}, {
__html: "<div>a</div>"
}, {
__html: "</div>"
}];`);
});

it('tansform with children and innnerHtml', () => {
expect(getTransfromCode(`
<div dangerouslySetInnerHTML={{__html: "<div>a</div>"}}>
123
</div>
`)).toBe(`[{
__html: "<div>"
}, {
__html: "<div>a</div>"
}, {
__html: "</div>"
}];`);
});
});
Loading

0 comments on commit f50cc43

Please # to comment.