I was trying to do a quick and dirty POC using vivliostyle, and I had some style leakage breaking into the viewer causing the viewer to render incorrectly. Figured that would be simple enough to solve by loading the viewer within a shadow root together with the global styles that are injected into the <head> by the CoreViewer, and initially everything seemed to work, except I realized that all "page overflow" is missing:
import("https://esm.run/@vivliostyle/core").then(({default: vivliostyle}) => {
const { CoreViewer } = vivliostyle;
const host = document.createElement("div");
document.body.appendChild(host);
const el = document.createElement("div");
// # broken scenario:
const shadowRoot = host.attachShadow({ mode: "open" });
shadowRoot.appendChild(el);
// # functioning scenario:
// host.appendChild(el);
const viewer = new CoreViewer({
viewportElement: el,
});
const str = `<!DOCTYPE html>
<html>
<head>
<style>
@page {
size: a5;
@bottom-left {
content: "Page " counter(page) "/" counter(pages);
}
}
p {
line-height: 1.5em;
}
#page-break-before {
page-break-before: always;
}
</style>
</head>
<body>
<p
>1 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla eget
ante feugiat, imperdiet massa vel, sagittis mi. Aenean metus velit,
blandit quis metus ac, suscipit aliquet nulla. Aenean ut enim dictum,
porta metus et, ultricies metus. Phasellus malesuada nisl lorem.
Praesent sagittis dui nulla, dictum luctus sem scelerisque ac. Nam
consequat a velit eu congue. Nulla id vestibulum orci. Sed quis
condimentum justo. Nunc bibendum tincidunt ipsum, ut pellentesque orci
egestas at. Curabitur pulvinar vitae purus et malesuada. Duis ex orci,
placerat ut lectus posuere, posuere rhoncus arcu. Vivamus in risus quis
mauris commodo venenatis id quis justo. Fusce interdum tincidunt
eleifend.</p
>
<p
>2 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla eget
ante feugiat, imperdiet massa vel, sagittis mi. Aenean metus velit,
blandit quis metus ac, suscipit aliquet nulla. Aenean ut enim dictum,
porta metus et, ultricies metus. Phasellus malesuada nisl lorem.
Praesent sagittis dui nulla, dictum luctus sem scelerisque ac. Nam
consequat a velit eu congue. Nulla id vestibulum orci. Sed quis
condimentum justo. Nunc bibendum tincidunt ipsum, ut pellentesque orci
egestas at. Curabitur pulvinar vitae purus et malesuada. Duis ex orci,
placerat ut lectus posuere, posuere rhoncus arcu. Vivamus in risus quis
mauris commodo venenatis id quis justo. Fusce interdum tincidunt
eleifend.</p
>
<p
>3 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla eget
ante feugiat, imperdiet massa vel, sagittis mi. Aenean metus velit,
blandit quis metus ac, suscipit aliquet nulla. Aenean ut enim dictum,
porta metus et, ultricies metus. Phasellus malesuada nisl enim lorem.
THIS TEXT IS MISSING. THIS TEXT IS MISSING. THIS TEXT IS MISSING.
THIS TEXT IS MISSING. THIS TEXT IS MISSING. THIS TEXT IS MISSING.
THIS TEXT IS MISSING. THIS TEXT IS MISSING. THIS TEXT IS MISSING.
THIS TEXT IS MISSING. THIS TEXT IS MISSING. THIS TEXT IS MISSING.
THIS TEXT IS MISSING. THIS TEXT IS MISSING. THIS TEXT IS MISSING.</p
>
<p id="page-break-before"
>4 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla eget
ante feugiat, imperdiet massa vel, sagittis mi. Aenean metus velit,
blandit quis metus ac, suscipit aliquet nulla. Aenean ut enim dictum,
porta metus et, ultricies metus. Phasellus malesuada nisl lorem.
Praesent sagittis dui nulla, dictum luctus sem scelerisque ac. Nam
consequat a velit eu congue. Nulla id vestibulum orci. Sed quis
condimentum justo. Nunc bibendum tincidunt ipsum, ut pellentesque orci
egestas at. Curabitur pulvinar vitae purus et malesuada. Duis ex orci,
placerat ut lectus posuere, posuere rhoncus arcu. Vivamus in risus quis
mauris commodo venenatis id quis justo. Fusce interdum tincidunt
eleifend.</p
>
</body>
</html>`;
const blob = new Blob([str], { type: "text/html" });
const blobUrl = URL.createObjectURL(blob);
viewer.loadDocument(
{
url: blobUrl,
},
undefined
);
window.viewer = viewer; // viewer.navigateToPage("next")
// the following isn't actually necessary to reproduce this issue
const vivlioStyles = [
"vivliostyle-viewport-screen-css",
"vivliostyle-viewport-css",
"vivliostyle-polyfill-css",
"vivliostyle-page-rules",
];
vivlioStyles.forEach((id) => {
const styleTag = document.getElementById(id);
if (styleTag) {
shadowRoot.appendChild(styleTag);
} else {
console.warn(`Style tag with id "${id}" not found.`);
}
});
});
Expected result: 3 pages, with page 2 stating "THIS TEXT IS MISSING.".
This can be observed by changing lines 7 to 12 to enable either the broken or functioning scenario.
I am well aware that loading the CoreViewer into a shadow root is probably... not the most standard thing to do, but I figured it was worth reporting anyway 🤷. Might even be a good idea for the CoreViewer in general to always load itself into the shadowRoot of the specified element, as that way it would guarantee that the styling will be the same as when the document would be printed from an iframe (as both an iframe and a shadowRoot would provide sandboxing of styles).
I was trying to do a quick and dirty POC using vivliostyle, and I had some style leakage breaking into the viewer causing the viewer to render incorrectly. Figured that would be simple enough to solve by loading the viewer within a shadow root together with the global styles that are injected into the
<head>by the CoreViewer, and initially everything seemed to work, except I realized that all "page overflow" is missing:Expected result: 3 pages, with page 2 stating "THIS TEXT IS MISSING.".
This can be observed by changing lines 7 to 12 to enable either the broken or functioning scenario.
I am well aware that loading the
CoreViewerinto a shadow root is probably... not the most standard thing to do, but I figured it was worth reporting anyway 🤷. Might even be a good idea for theCoreViewerin general to always load itself into the shadowRoot of the specified element, as that way it would guarantee that the styling will be the same as when the document would be printed from an iframe (as both an iframe and a shadowRoot would provide sandboxing of styles).