Skip to content

Instantly share code, notes, and snippets.

@moodysalem
Created November 22, 2016 16:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moodysalem/11eff7a21a7bf9a93612b9c8ec0bd2e3 to your computer and use it in GitHub Desktop.
Save moodysalem/11eff7a21a7bf9a93612b9c8ec0bd2e3 to your computer and use it in GitHub Desktop.
Render a react component to an html document that shares all the links and styles for printing, and convert it to a data URI for window.open
import React, { PureComponent, PropTypes } from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { Base64 } from 'js-base64';
import Promise from 'bluebird';
const htmlDocTemplate = ({ links, pageStyles, body, title = 'Print' }) => (`
<html>
<head>
<title>${title}</title>
${links}
<style>${pageStyles}</style>
</head>
<body>${body}</body>
<script>window.print();</script>
</html>
`);
const templateToUri = html => (
`data:text/html;base64,${encodeURIComponent(Base64.encode(html))}`
);
export default function renderComponentToPrintHtml(component) {
return new Promise((resolve, reject) => {
const _el = document.createElement('div');
_el.style.display = 'none';
document.body.appendChild(_el);
try {
render(component, _el);
// collect all the link tags that link to stylesheets
const links = _.chain(document.getElementsByTagName('link'))
.filter(l => l.rel && l.rel.toLowerCase() == 'stylesheet')
.map(l => l.outerHTML)
.value().join('\n');
// collect all the style tags in the document
const pageStyles = _.map(document.getElementsByTagName('style'), el => el.innerHTML).join('\n');
resolve(
templateToUri(
htmlDocTemplate({ links, pageStyles, body: _el.innerHTML })
)
);
unmountComponentAtNode(_el);
} catch (err) {
reject(err);
}
document.body.removeChild(_el);
});
};
@moodysalem
Copy link
Author

This isn't an asynchronous function as written, but it could be re-written to use a web worker (web workers don't have access to the DOM so this is a lot more work)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment