I would like to render a full html page(with html and body tags) with content provided by a render array.
What do I need to do in order to NOT render attachments(CSS, JS, drupalSettings) from active theme or modules but solely from attachments defined in the provided render array?
So far this is quite close but I still see attachments from base theme:
\Drupal::service('bare_html_page_renderer')
->renderBarePage(
$my_render_array,
'Page label',
'page',
[]
);
Using my own, empty, theme hasn't helped.
Ok, I had to duplicate what bare_html_page_renderer did since it attached "default" libraries form the system module. So now with my own theme all looks good but the structure is not right. Seems like the placeholders are not working properly.
My html.html.twig source code looks like:
<!DOCTYPE html>
<html{{ html_attributes }}>
<head>
<head-placeholder token="{{ placeholder_token }}">
<title>{{ head_title|safe_join(' | ') }}</title>
<css-placeholder token="{{ placeholder_token }}">
<js-placeholder token="{{ placeholder_token }}">
</head>
<body{{ attributes }}>
{{ page }}
<js-bottom-placeholder token="{{ placeholder_token }}">
</body>
</html>
but the rendered HTML will looks like:
<html dir="ltr" lang="en">
<head> </head>
<body>
<head-placeholder token="...">
<title>Page title</title>
<link rel="stylesheet" href="..." media="all">
<div>the rendered content</div>
<script src="...">
</head-placeholder>
</body>
</html>
So the issue was the there has to be at least one attribute in the header, otherwise the 'head' placeholder won't be replaced. So adding a favicon or generator or any metatag will do the trick.
Unfortunately this works only for route response with theme negotiator but not if I just want to print the pure html code since the active theme will be applied.