Preprocess certain CSS values before PDF rendering to fix html2canvas limitations

This commit is contained in:
Andrew Kingston 2025-04-01 20:06:44 +01:00
parent c8de60eb8e
commit 651ac10de3
No known key found for this signature in database
4 changed files with 43 additions and 23 deletions

View File

@ -57,12 +57,6 @@
let permissionError = false let permissionError = false
let embedNoScreens = false let embedNoScreens = false
// Get theme class names, which is always lightest for LDFs
$: isPDFScreen = $screenStore.activeScreen?.variant === ScreenVariant.PDF
$: themeClassNames = isPDFScreen
? "spectrum--light"
: getThemeClassNames($themeStore.theme)
// Determine if we should show devtools or not // Determine if we should show devtools or not
$: showDevTools = $devToolsEnabled && !$routeStore.queryParams?.peek $: showDevTools = $devToolsEnabled && !$routeStore.queryParams?.peek
@ -164,7 +158,7 @@
id="spectrum-root" id="spectrum-root"
lang="en" lang="en"
dir="ltr" dir="ltr"
class="spectrum spectrum--medium {themeClassNames}" class="spectrum spectrum--medium {getThemeClassNames($themeStore.theme)}"
class:builder={$builderStore.inBuilder} class:builder={$builderStore.inBuilder}
class:show={fontsLoaded && dataLoaded} class:show={fontsLoaded && dataLoaded}
> >

View File

@ -1,12 +1,18 @@
<script> <script>
import { themeStore } from "@/stores" import { themeStore } from "@/stores"
import { setContext } from "svelte" import { setContext } from "svelte"
import { Context } from "@budibase/bbui" import { Context, Helpers } from "@budibase/bbui"
setContext(Context.PopoverRoot, "#theme-root") export let popoverRoot = true
const id = Helpers.uuid()
if (popoverRoot) {
setContext(Context.PopoverRoot, `#id`)
}
</script> </script>
<div style={$themeStore.customThemeCss} id="theme-root"> <div style={$themeStore.customThemeCss} {id}>
<slot /> <slot />
</div> </div>

View File

@ -3,6 +3,7 @@
import { Heading, Button } from "@budibase/bbui" import { Heading, Button } from "@budibase/bbui"
import { htmlToPdf, pxToPt, A4HeightPx, type PDFOptions } from "./pdf" import { htmlToPdf, pxToPt, A4HeightPx, type PDFOptions } from "./pdf"
import { GridRowHeight } from "@/constants" import { GridRowHeight } from "@/constants"
import CustomThemeWrapper from "@/components/CustomThemeWrapper.svelte"
const component = getContext("component") const component = getContext("component")
const { styleable, Block, BlockComponent } = getContext("sdk") const { styleable, Block, BlockComponent } = getContext("sdk")
@ -30,6 +31,7 @@
const generatePDF = async () => { const generatePDF = async () => {
rendering = true rendering = true
await tick() await tick()
preprocessCSS()
try { try {
const opts: PDFOptions = { const opts: PDFOptions = {
fileName: safeName, fileName: safeName,
@ -43,6 +45,16 @@
rendering = false rendering = false
} }
const preprocessCSS = () => {
const els = document.getElementsByClassName(
"grid-child"
) as unknown as HTMLElement[]
for (let el of els) {
const styles = window.getComputedStyle(el)
el.style.setProperty("grid-column-end", styles.gridColumnEnd, "important")
}
}
const getDividerStyle = (idx: number) => { const getDividerStyle = (idx: number) => {
const top = (idx + 1) * innerPageHeightPx + doubleMarginPx / 2 const top = (idx + 1) * innerPageHeightPx + doubleMarginPx / 2
return `--idx:"${idx + 1}"; --top:${top}px;` return `--idx:"${idx + 1}"; --top:${top}px;`
@ -90,19 +102,24 @@
/> />
{/each} {/each}
{/if} {/if}
<div class="pageContent" bind:this={ref}> <div
<BlockComponent class="spectrum spectrum--medium spectrum--lightest pageContent"
type="container" bind:this={ref}
props={{ layout: "grid" }} >
styles={{ <CustomThemeWrapper popoverRoot={false}>
normal: { <BlockComponent
height: `${gridMinHeight}px`, type="container"
}, props={{ layout: "grid" }}
}} styles={{
context="grid" normal: {
> height: `${gridMinHeight}px`,
<slot /> },
</BlockComponent> }}
context="grid"
>
<slot />
</BlockComponent>
</CustomThemeWrapper>
</div> </div>
</div> </div>
</div> </div>

View File

@ -116,6 +116,9 @@ export const gridLayout = (node: HTMLDivElement, metadata: GridMetadata) => {
return return
} }
// Add a unique class to elements we mutate so we can easily find them later
node.classList.add("grid-child")
// Callback to select the component when clicking on the wrapper // Callback to select the component when clicking on the wrapper
selectComponent = (e: Event) => { selectComponent = (e: Event) => {
e.stopPropagation() e.stopPropagation()