Merge origin/main into origin/dev-moritz

This commit is contained in:
Moritz Utcke
2025-01-12 14:25:35 +07:00
parent f16fb41db0
commit f8402a0136
54 changed files with 4907 additions and 130 deletions

View File

@@ -0,0 +1,105 @@
import * as txml from "#lib/helpers/txml.js"
import { PDFDocument, PDFFont, rgb, StandardFonts } from "pdf-lib"
import { Checkbox, Flex, Text } from "./index.js"
import { Layout } from "./Layout.js"
import { PDFElement } from "./PDFElement.js"
export function xml2pdf(xml: string, font: PDFFont) {
const tree = txml.parse(xml)
const iterateChildren = (children: ReturnType<typeof txml.parse>, parent: PDFElement) => {
for (const child of children) {
if (typeof child === "string") {
// Simple text
parent.addChild(new Text(child, { font }))
} else if (child.tagName === "flex") {
const flexbox = new Flex({
height: parseFloat(child.attributes.height) || "auto",
width: parseFloat(child.attributes.width) || "auto",
align: child.attributes.align,
direction: child.attributes.direction,
gap: parseFloat(child.attributes.gap) || 0,
justify: child.attributes.justify
})
iterateChildren(child.children, flexbox)
parent.addChild(flexbox)
} else if (child.tagName === "text") {
let color = rgb(0,0,0)
if (child.attributes.hasOwnProperty("color")) {
const colorValue = child.attributes.color.split(",")
if (colorValue.length !== 3) {
throw new Error("Invalid color, please provide 'r,g,b' as a value.")
}
color = rgb(...colorValue.map((x) => parseInt(x) / 255) as [number, number, number]);
}
const text = new Text(child.children[0] || "", { font: child.attributes.hasOwnProperty("bold") ? bold : font, fontSize: parseFloat(child.attributes.size) || 10, color })
parent.addChild(text)
} else if (child.tagName === "checkbox") {
if (typeof child.attributes.width === "undefined" || typeof child.attributes.height === "undefined") {
throw new Error("Missing height or width property in Checkbox creation.")
}
const checkbox = new Checkbox(parseFloat(child.attributes.width), parseFloat(child.attributes.height))
parent.addChild(checkbox);
} else if (child.tagName === "layout") {
const layout = new Layout([], {
margin: {
bottom: parseFloat(child.attributes.marginBottom) || 0,
left: parseFloat(child.attributes.marginLeft) || 0,
right: parseFloat(child.attributes.marginRight) || 0,
top: parseFloat(child.attributes.marginTop) || 0,
},
padding: {
bottom: parseFloat(child.attributes.paddingBottom) || 0,
left: parseFloat(child.attributes.paddingLeft) || 0,
right: parseFloat(child.attributes.paddingRight) || 0,
top: parseFloat(child.attributes.paddingTop) || 0,
}
})
iterateChildren(child.children, layout)
parent.addChild(layout)
}
}
}
const layout = new Layout([]);
iterateChildren(tree, layout)
return layout
}
const pdf = await PDFDocument.create()
const page = pdf.addPage()
const font = await pdf.embedFont(StandardFonts.Helvetica)
const bold = await pdf.embedFont(StandardFonts.HelveticaBold)
const layout = xml2pdf(`<layout height="${page.getHeight()}" width="${page.getWidth()}" marginTop="0" marginLeft="0">
<text bold size="40">Hello</text>
<text color="255,0,255" size="24">Hello, how are you?</text>
<flex direction="row" gap="8" align="center">
<checkbox height="100" width="100"></checkbox>
<text>Hello</text>
<layout marginLeft="0">
<text>Hello</text>
<text>Nasya, i love you</text>
</layout>
</flex>
</layout>`, font)
layout.draw(page, 0, page.getHeight())
import { writeFileSync } from "fs"
import { FixedLengthArray } from "#lib/Berechnungen/BedarfsausweisWohnen/types.js"
writeFileSync("./test-pdf.pdf", await pdf.save())