-
Notifications
You must be signed in to change notification settings - Fork 25
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
Add possibility to provide a external preview renderer endpoint #65
Comments
In our Slack channel, a developer came up with the following solution in his project. I have not tested this because I do not have the usecase, but maybe this will help somebody else 🙂 <iframe
style="position:fixed; top:0; left:0; bottom:0; right:0; width:100%; height:100%; border:none; margin:0; padding:0; overflow:hidden; z-index:999999;"
id='__NUXT__'
src="//{{ frontend_url }}{{ content.url }}?preview=true"></iframe>
<script>
var frame = document.getElementById('__NUXT__')
frame.onload = function(){
frame.contentWindow.postMessage({{ jsonData|raw }}, '*')
}
</script> |
On The frontend side you can add this one to get the content :) if ((this as any).$route.query.preview) {
window.addEventListener(
'message',
(event) => {
if (event.data) {
;(this as any).$store.dispatch('content/preview', {
content: event.data.content,
view: event.data.view,
})
}
},
false
)
}
}, |
Full Example can look like the following: Adding the following to all your templates: <view>pages/headless</view> Then create this template which will include the iframe: <!doctype html>
<html lang="{{ app.request.locale }}">
<head>
<title>Preview</title>
<style>
body {
margin: 0;
}
#application-frame {
border: 0;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
</style>
</head>
<body>
{% if app.request.attributes.get('preview') %}
<iframe id="application-frame" src="http://127.0.0.1:8089/test.html"></iframe>
{% endif %}
{% block content %}
{% if app.request.attributes.get('preview') %}
<script>
var frame = document.getElementById('application-frame');
frame.onload = function() {
frame.contentWindow.postMessage({{ headless|json_encode|raw }}, '*'); // TODO * should be replaced by correct origin
}
</script>
{% endif %}
{% endblock %}
</body>
</html> The app side could look like this <!doctype html>
<html lang="en">
<head>
<title>Test</title>
<style>body { background: red; }</style>
</head>
<body>
<pre id="content">
Waiting for data ...
</pre>
<script>
window.addEventListener(
'message',
function(event) {
// TODO this should be checked to avoid unsecure data being send from other origin
// if (event.origin !== 'https://expected-origin-address') {
// return;
// }
if (event.data) {
document.getElementById('content').innerText = JSON.stringify(event.data, null, 4);
}
},
false
)
</script>
</body>
</html> |
The solution with the iframe and postMessage feels from my side good. We still would need the possibility to configure an URL (iframe) so there are for me 2 open points for this issue. 1. Where to configure the url and how to handle multi webspace support Simple configuration: sulu_headless:
preview_url: '%env(PREVIEW_ENDPONT)%' Multi Webspace endpoint: sulu_headless:
preview_url:
webspace_a: '%env(PREVIEW_WEBSPACE_A_ENDPONT)%'
webspace_b: '%env(PREVIEW_WEBSPACE_B_ENDPONT)%' With some symfony config magic this given config can be detected and correctly converted into the array of available webspaces. So we just need a twig extension to get the preview url e.g.: {% set previewUrl = sulu_headless_preview_url(request.webspace) %} 2. Security for the postMessage The postMessage has a security included that only postMessage can be receive which targetOrigin does match. As mention in the documentation about postMessage: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage this should always be used to avoid sending data to maybe an external website which should not happen. |
When you are using nextJS or something similar the preview HTML need also be rendered by the nextJS server. This could be implemented in the Headless Controller the following way.
The text was updated successfully, but these errors were encountered: