diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..dd71d2d --- /dev/null +++ b/.babelrc @@ -0,0 +1,8 @@ +{ + "presets": [ + "airbnb" + ], + "plugins":[ + [ "transform-react-jsx", { "progma": "h" } ] + ] +} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3f999da --- /dev/null +++ b/.editorconfig @@ -0,0 +1,3 @@ +[*] +indent_size = 2 +indent_style = space \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..b8e390a --- /dev/null +++ b/.eslintrc @@ -0,0 +1,8 @@ +{ + "extends": [ + "airbnb-base" + ], + "rules": { + "import/no-unresolved": 0 + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2021497 --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +# Logs +logs +*.log +npm-debug.log* + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +node_modules + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +TODO +coverage +lib + +# Only apps should have lockfiles +npm-shrinkwrap.json +yarn.lock +package-lock.json +© 2019 GitHub, Inc. +Terms +Privacy +Security +Status +Help +Contact GitHub +Pricing +API +Training +Blog +About + +example \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e56ea20 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019 Felipe Guizar Diaz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3ee06ab --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# hypernova-preact + +[Preact](https://preactjs.com) bindings for [Hypernova](https://github.com/airbnb/hypernova). + +On the server, wraps the component in a function to render it to a HTML string given its props. + +On the client, calling this function with your component scans the DOM for any server-side rendered instances of it. It then resumes those components using the server-specified props. + +## Install + +```sh +npm install hypernova-preact +``` + +## Usage + +Here's how to use it in your module: + +```js +import { renderPreact } from 'hypernova-preact' +import Example from './components/Example' + +export default renderPreact('Example', Example) +``` \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..f1431fa --- /dev/null +++ b/package.json @@ -0,0 +1,37 @@ +{ + "name": "hypernova-preact", + "version": "1.0.1", + "description": "Preact Bindings for Hypernova", + "main": "lib/index.js", + "author": "Felipe Guizar Diaz ", + "license": "MIT", + "keywords": [ + "preact", + "hypernova", + "ssr", + "isomorphic", + "universal" + ], + "repository": { + "type": "git", + "url": "git@github.com:ara-framework/hypernova-preact.git" + }, + "scripts": { + "prepublish": "npm run build", + "lint": "eslint src", + "build": "babel src -d lib", + "dev": "babel src -d lib -w" + }, + "dependencies": { + "hypernova": "^2.5.0", + "preact": "^8.4.2", + "preact-render-to-string": "^4.1.0" + }, + "peerDependencies": { + "babel-cli": "^6.26.0", + "babel-preset-airbnb": "^2.5.3", + "eslint": "^5.14.1", + "eslint-config-airbnb-base": "^13.1.0", + "eslint-plugin-import": "^2.16.0" + } +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..61b7d4e --- /dev/null +++ b/src/index.js @@ -0,0 +1,28 @@ +/* eslint-disable import/prefer-default-export */ +import hypernova, { serialize, load } from 'hypernova'; +import { h, render } from 'preact'; +import renderToString from 'preact-render-to-string'; + +export const renderPreact = (name, component) => hypernova({ + server() { + return (props) => { + const html = renderToString(h(component, props)); + return serialize(name, html, props); + }; + }, + + client() { + const payloads = load(name); + + if (payloads) { + payloads.forEach((payload) => { + const { node, data } = payload; + const element = h(component, data); + + render(element, node, node.firstElementChild); + }); + } + + return component; + }, +});