Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Supply HTML Template for Playroom & Preview #189

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Expand Up @@ -68,11 +68,20 @@ module.exports = {
// Custom webpack config goes here...
}),
iframeSandbox: 'allow-scripts',

// Advanced options (optional):
htmlTemplate: {
// Keys are constant here, always `/̀ and `/preview`, even if basePath is specified
'/': './pathToMainTemplate.ejs',
'/preview': './pathToPreviewTemplate.ejs',
},
};
```

_Note: `port` and `openBrowser` options will be set to `9000` and `true` (respectively) by default whenever they are omitted from the config above._

_Note 2: `htmlTemplate` templates will be loaded by [HtmlWebpackPlugin](https://github.com/jantimon/html-webpack-plugin). For advanced templating options, see their [documentation](https://github.com/jantimon/html-webpack-plugin/blob/master/docs/template-option.md) on this option (named `template` and not `htmlTemplate` like Playroom) or the [default template](https://github.com/jantimon/html-webpack-plugin/blob/master/default_index.ejs) used. Insert an element with ID `root` in your HTML and Playroom will be rendered in it. Note that unless you explicitely render the config title option, the title used for the document will be the one you hardcode in your template file._

Your `components` file is expected to export a single object or a series of named exports. For example:

```js
Expand Down
4 changes: 4 additions & 0 deletions cypress/projects/themed/playroom.config.js
Expand Up @@ -7,4 +7,8 @@ module.exports = {
paramType: 'search',
port: 9001,
storageKey: 'playroom-example-themed',
htmlTemplate: {
'/': './template.ejs',
'/preview': './preview-template.ejs',
},
};
13 changes: 13 additions & 0 deletions cypress/projects/themed/preview-template.ejs
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="root"></div>
<script type="text/javascript">
console.info('Dummy code appended after Playroom Preview...');
</script>
</body>
</html>
13 changes: 13 additions & 0 deletions cypress/projects/themed/template.ejs
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="root"></div>
<script type="text/javascript">
console.info('Dummy code appended after Playroom...');
</script>
</body>
</html>
13 changes: 13 additions & 0 deletions lib/makeWebpackConfig.js
Expand Up @@ -147,6 +147,10 @@ module.exports = async (playroomConfig, options) => {
chunks: ['index'],
filename: 'index.html',
base: playroomConfig.baseUrl,
// Spread the template option, since setting it to null, undefined or "" if none is specified causes an issue.
...(playroomConfig.htmlTemplate && playroomConfig.htmlTemplate['/']
? { template: relativeResolve(playroomConfig.htmlTemplate['/']) }
: {}),
}),
new HtmlWebpackPlugin({
title: 'Playroom Frame',
Expand All @@ -159,6 +163,15 @@ module.exports = async (playroomConfig, options) => {
chunksSortMode: 'none',
chunks: ['preview'],
filename: 'preview/index.html',
// Spread the template option, since setting it to null, undefined or "" if none is specified causes an issue.
...(playroomConfig.htmlTemplate &&
playroomConfig.htmlTemplate['/preview']
? {
template: relativeResolve(
playroomConfig.htmlTemplate['/preview']
),
}
: {}),
}),
...(options.production
? []
Expand Down
26 changes: 26 additions & 0 deletions src/get-or-create-root.js
@@ -0,0 +1,26 @@
/**
* Get or create the root where we want to render Playroom.
* - If `configPath` is set, use an element with ID "root" as the root.
* - If no template is provided, simply create a `<div />` element and return it.
*
* @param configPath Path to the HTML template
*/
module.exports = (configPath) => {
if (configPath) {
const root = document.getElementById('root');

if (!root) {
// If #root element is not found, throw error as we won't be able to render Playroom.
throw new Error(
'No element found in body with ID "root". Playroom won\'t be rendered. Put a `<div id="root"></div>` in your HTML template where you want to render Playroom.'
);
}

return root;
}

const outlet = document.createElement('div');
document.body.appendChild(outlet);

return outlet;
};
9 changes: 5 additions & 4 deletions src/index.js
Expand Up @@ -3,6 +3,7 @@ import { render } from 'react-dom';

import Playroom from './Playroom/Playroom';
import { StoreProvider } from './StoreContext/StoreContext';
import getOrCreateRoot from './get-or-create-root';
import playroomConfig from './config';

const polyfillIntersectionObserver = () =>
Expand All @@ -12,9 +13,9 @@ const polyfillIntersectionObserver = () =>

polyfillIntersectionObserver().then(() => {
const widths = playroomConfig.widths || [320, 375, 768, 1024];

const outlet = document.createElement('div');
document.body.appendChild(outlet);
const root = getOrCreateRoot(
playroomConfig.htmlTemplate && playroomConfig.htmlTemplate['/']
);

const renderPlayroom = ({
themes = require('./themes'),
Expand All @@ -36,7 +37,7 @@ polyfillIntersectionObserver().then(() => {
}
/>
</StoreProvider>,
outlet
root
);
};
renderPlayroom();
Expand Down
9 changes: 6 additions & 3 deletions src/preview.js
@@ -1,9 +1,12 @@
import React from 'react';
import { render } from 'react-dom';
import Preview from './Playroom/Preview';
import playroomConfig from './config';
import getOrCreateRoot from './get-or-create-root';

const outlet = document.createElement('div');
document.body.appendChild(outlet);
const root = getOrCreateRoot(
playroomConfig.htmlTemplate && playroomConfig.htmlTemplate['/preview']
);

const renderPreview = ({
themes = require('./themes'),
Expand All @@ -16,7 +19,7 @@ const renderPreview = ({
themes={themes}
FrameComponent={FrameComponent}
/>,
outlet
root
);
};
renderPreview();
Expand Down