├── .npmignore ├── .babelrc ├── lib ├── __tests__ │ ├── html.jsx │ └── compile.test.js └── compile.js ├── .gitignore ├── index.js ├── LICENSE-MIT ├── package.json └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | *.test.js 2 | *.jsx 3 | .babelrc 4 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ "es2015", "react" ] 3 | } 4 | -------------------------------------------------------------------------------- /lib/__tests__/html.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | export default (props) => 3 | {props.children} 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore system files 2 | 3 | # OS X 4 | .DS_Store 5 | .Spotlight-V100 6 | .Trashes 7 | ._* 8 | 9 | # Win 10 | Thumbs.db 11 | Desktop.ini 12 | 13 | # vim 14 | *~ 15 | .swp 16 | .*.sw[a-z] 17 | Session.vim 18 | 19 | # Node 20 | node_modules 21 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* global hexo */ 2 | 'use strict' 3 | 4 | var compile = require('./lib/compile') 5 | 6 | function renderer (data, locals) { 7 | return compile(data)(locals) 8 | } 9 | 10 | renderer.compile = compile 11 | 12 | hexo.extend.renderer.register('jsx', 'html', renderer, true) 13 | -------------------------------------------------------------------------------- /lib/compile.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var babel = require('babel-core') 4 | var React = require('react') 5 | var ReactDOMServer = require('react-dom/server') 6 | var reval = require('eval') 7 | require('babel-core/register') 8 | 9 | module.exports = function compile (data) { 10 | var js = babel.transform(data.text, { filename: data.path }) 11 | var Component = reval(js.code, data.path, null, true) 12 | 13 | return function (locals) { 14 | var element = React.createElement(Component.default || Component, locals) 15 | var markup = ReactDOMServer.renderToStaticMarkup(element) 16 | 17 | if (markup.slice(0, 5).toLowerCase() === '=0.14", 31 | "react-dom": ">=0.14" 32 | }, 33 | "devDependencies": { 34 | "babel-preset-es2015": "^6.14.0", 35 | "babel-preset-react": "^6.11.1", 36 | "mocha": "^3.0.0", 37 | "react": "^15.0.0", 38 | "react-dom": "^15.0.0", 39 | "standard": "^8.0.0" 40 | }, 41 | "scripts": { 42 | "pre-test": "standard", 43 | "test": "mocha 'lib/__tests__/*.js'" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/__tests__/compile.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const join = require('path').join 6 | const compile = require('../compile') 7 | 8 | const TEMPLATE_PATH = join(__dirname, 'template.jsx') 9 | 10 | describe('hexo-renderer-react/lib/compile', () => { 11 | it('returns function to render html strings', () => { 12 | const template = ` 13 | var React = require('react') 14 | module.exports = React.createClass({ 15 | render: function () { 16 | return React.createElement('div', { className: 't1' }, 'test') 17 | } 18 | }) 19 | ` 20 | 21 | const compiled = compile({ text: template, path: TEMPLATE_PATH }) 22 | assert.equal(typeof compiled, 'function') 23 | 24 | const rendered = compiled() 25 | assert.equal(rendered, '
test
') 26 | }) 27 | 28 | it('handles es6 and jsx', () => { 29 | const template = ` 30 | import React from 'react' 31 | export default () => 32 |
test
33 | ` 34 | 35 | const rendered = compile({ text: template, path: TEMPLATE_PATH })() 36 | assert.equal(rendered, '
test
') 37 | }) 38 | 39 | it('prepends doctype if top node is html', () => { 40 | const template = ` 41 | import React from 'react' 42 | export default () => 43 | test 44 | ` 45 | 46 | const rendered = compile({ text: template, path: TEMPLATE_PATH })() 47 | assert.equal(rendered, '\ntest') 48 | }) 49 | 50 | it('handles imported components', () => { 51 | const template = ` 52 | import React from 'react' 53 | import Html from './html.jsx' 54 | export default () => 55 | test 56 | ` 57 | 58 | const rendered = compile({ text: template, path: TEMPLATE_PATH })() 59 | assert.equal(rendered, '\ntest') 60 | }) 61 | 62 | it('passes locals as props', () => { 63 | const template = ` 64 | import React from 'react' 65 | export default (props) => 66 |
{props.message}
67 | ` 68 | 69 | const rendered = compile({ text: template, path: TEMPLATE_PATH })({ 70 | message: 'Test Message' 71 | }) 72 | assert.equal(rendered, '
Test Message
') 73 | }) 74 | }) 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hexo-renderer-react 2 | 3 | > Render ES6 React components as hexo templates 4 | 5 | [![npm Version][npm-image]][npm] 6 | [![Dependency Status][deps-image]][deps] 7 | [![Dev Dependency Status][dev-deps-image]][dev-deps] 8 | 9 | [![JS Standard Style][style-image]][style] 10 | [![MIT License][license-image]][LICENSE] 11 | 12 | 13 | ## Install 14 | 15 | ``` bash 16 | $ npm install hexo-renderer-react react react-dom --save 17 | ``` 18 | 19 | This requires you to have `react` installed as well. 20 | 21 | 22 | ## Usage 23 | 24 | * Name your components with the `.jsx` extension 25 | * `export default` or `module.exports =` your component class 26 | * ES6/7 syntax and JSX is handled by [`babel`][babel] Version 6 27 | * `.babelrc` Config file [preset requirements][babel-6-setup]: 28 | * [babel-preset-es2015][babel-preset-es2015] 29 | * [babel-preset-react][babel-preset-react] 30 | * [babel-preset-stage-0][babel-preset-stage-0] 31 | 32 | ### Examples 33 | 34 | *layout.jsx* 35 | ```js 36 | import React from 'react'; 37 | 38 | export default class extends React.Component { 39 | render() { 40 | return ( 41 | 42 | 43 | {this.props.page.title} 44 | 45 | 46 |
47 | 48 | 49 | ); 50 | } 51 | } 52 | ``` 53 | 54 | *post.jsx* 55 | ```js 56 | import React from 'react'; 57 | 58 | export default class extends React.Component { 59 | render() { 60 | return ( 61 |
62 |

POST: {this.props.page.title}

63 |
{this.props.page.date.toString()}
64 |
65 | ) 66 | } 67 | } 68 | ``` 69 | 70 | 71 | ## License 72 | 73 | This software is free to use under the MIT license. See the 74 | [LICENSE-MIT file][LICENSE] for license text and copyright information. 75 | 76 | 77 | [npm]: https://www.npmjs.org/package/hexo-renderer-react 78 | [npm-image]: https://img.shields.io/npm/v/hexo-renderer-react.svg 79 | [deps]: https://david-dm.org/thetalecrafter/hexo-renderer-react 80 | [deps-image]: https://img.shields.io/david/thetalecrafter/hexo-renderer-react.svg 81 | [dev-deps]: https://david-dm.org/thetalecrafter/hexo-renderer-react#info=devDependencies 82 | [dev-deps-image]: https://img.shields.io/david/dev/thetalecrafter/hexo-renderer-react.svg 83 | [style]: https://github.com/feross/standard 84 | [style-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg 85 | [license-image]: https://img.shields.io/npm/l/hexo-renderer-react.svg 86 | [babel]: https://github.com/babel/babel 87 | [babel-6-setup]: http://babeljs.io/blog/2015/10/31/setting-up-babel-6/ 88 | [babel-preset-es2015]: https://www.npmjs.com/package/babel-preset-es2015 89 | [babel-preset-react]: https://www.npmjs.com/package/babel-preset-react 90 | [babel-preset-stage-0]: https://www.npmjs.com/package/babel-preset-stage-0 91 | [LICENSE]: https://github.com/thetalecrafter/hexo-renderer-react/blob/master/LICENSE-MIT 92 | --------------------------------------------------------------------------------