Remove 'fill-sample-template.js' script to streamline the project and eliminate unused functionality. Update 'smoke-test.js' to reflect this change by removing the call to the deleted script.
This commit is contained in:
@@ -1,258 +0,0 @@
|
|||||||
import fs from 'fs'
|
|
||||||
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib'
|
|
||||||
|
|
||||||
async function fill() {
|
|
||||||
const templatePath = 'server/templates/mitgliedschaft-fillable.pdf'
|
|
||||||
if (!fs.existsSync(templatePath)) {
|
|
||||||
console.error('Template not found:', templatePath)
|
|
||||||
process.exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const existingPdfBytes = fs.readFileSync(templatePath)
|
|
||||||
const pdfDoc = await PDFDocument.load(existingPdfBytes)
|
|
||||||
const form = pdfDoc.getForm()
|
|
||||||
|
|
||||||
// Ensure a readable font is embedded and used for field appearances
|
|
||||||
const helv = await pdfDoc.embedFont(StandardFonts.Helvetica)
|
|
||||||
|
|
||||||
// Simple sample data
|
|
||||||
const sample = {
|
|
||||||
nachname: 'Müller',
|
|
||||||
vorname: 'Anna',
|
|
||||||
strasse: 'Hauptstr. 12',
|
|
||||||
plz_ort: '60389 Frankfurt',
|
|
||||||
geburtsdatum: '01.01.1990',
|
|
||||||
telefon: '069 123456',
|
|
||||||
email: 'anna.mueller@example.de',
|
|
||||||
telefon_mobil: '0151 2345678',
|
|
||||||
mitglied_aktiv: true,
|
|
||||||
mitglied_passiv: false,
|
|
||||||
sepa_mitglied: 'Anna Müller',
|
|
||||||
sepa_kontoinhaber: 'Anna Müller',
|
|
||||||
sepa_strasse: 'Hauptstr. 12',
|
|
||||||
sepa_plz_ort: '60389 Frankfurt',
|
|
||||||
sepa_bank: 'Sparkasse',
|
|
||||||
sepa_iban: 'DE00123456781234567890',
|
|
||||||
sepa_bic: 'PBNKDEFF',
|
|
||||||
sepa_datum: '23.10.2025',
|
|
||||||
sign_datum: '23.10.2025',
|
|
||||||
page3_name: 'Müller',
|
|
||||||
page3_vorname: 'Anna',
|
|
||||||
page3_anschrift: 'Hauptstr. 12, 60389 Frankfurt',
|
|
||||||
page3_telefon: '069 123456',
|
|
||||||
page3_fax: '069 654321',
|
|
||||||
page3_email: 'anna.mueller@example.de',
|
|
||||||
page3_datum: '23.10.2025'
|
|
||||||
}
|
|
||||||
|
|
||||||
function safeSetText(name, value) {
|
|
||||||
try {
|
|
||||||
const f = form.getTextField(name)
|
|
||||||
f.setText(value)
|
|
||||||
} catch (e) {
|
|
||||||
// ignore missing fields
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Robust setter: find a field by name (case-insensitive) and set text/checkbox/select accordingly
|
|
||||||
function setFieldByName(name, value) {
|
|
||||||
try {
|
|
||||||
const lower = name.toLowerCase()
|
|
||||||
const field = form.getFields().find(f => f.getName() && f.getName().toLowerCase() === lower)
|
|
||||||
if (!field) {
|
|
||||||
console.log(`DEBUG: Field not found for '${name}'`)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Text field
|
|
||||||
if (typeof field.setText === 'function') {
|
|
||||||
field.setText(value == null ? '' : String(value))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// Check box
|
|
||||||
if (typeof field.check === 'function') {
|
|
||||||
if (value === true || String(value).toLowerCase() === 'true') field.check()
|
|
||||||
else if (typeof field.uncheck === 'function') field.uncheck()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// Radio/select (pdf-lib uses select for dropdowns)
|
|
||||||
if (typeof field.select === 'function') {
|
|
||||||
try { field.select(String(value)) } catch (e) { /* ignore */ }
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
console.log(`DEBUG: Unsupported field type for '${name}'`)
|
|
||||||
return false
|
|
||||||
} catch (e) {
|
|
||||||
console.log(`DEBUG: Error setting field '${name}':`, e.message)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debug: list all form fields found in the template
|
|
||||||
try {
|
|
||||||
const allFields = form.getFields().map(f => f.getName())
|
|
||||||
console.log('DEBUG: Template form fields:', allFields.join(', '))
|
|
||||||
} catch (e) {
|
|
||||||
console.log('DEBUG: Could not list form fields:', e.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
setFieldByName('nachname', sample.nachname)
|
|
||||||
setFieldByName('vorname', sample.vorname)
|
|
||||||
setFieldByName('strasse', sample.strasse)
|
|
||||||
setFieldByName('plz_ort', sample.plz_ort)
|
|
||||||
setFieldByName('geburtsdatum', sample.geburtsdatum)
|
|
||||||
setFieldByName('telefon', sample.telefon)
|
|
||||||
setFieldByName('email', sample.email)
|
|
||||||
setFieldByName('telefon_mobil', sample.telefon_mobil)
|
|
||||||
|
|
||||||
// Checkboxes via robust setter
|
|
||||||
setFieldByName('mitglied_aktiv', sample.mitglied_aktiv)
|
|
||||||
setFieldByName('mitglied_passiv', sample.mitglied_passiv)
|
|
||||||
|
|
||||||
setFieldByName('sepa_mitglied', sample.sepa_mitglied)
|
|
||||||
setFieldByName('sepa_kontoinhaber', sample.sepa_kontoinhaber)
|
|
||||||
setFieldByName('sepa_strasse', sample.sepa_strasse)
|
|
||||||
setFieldByName('sepa_plz_ort', sample.sepa_plz_ort)
|
|
||||||
setFieldByName('sepa_bank', sample.sepa_bank)
|
|
||||||
setFieldByName('sepa_iban', sample.sepa_iban)
|
|
||||||
setFieldByName('sepa_bic', sample.sepa_bic)
|
|
||||||
setFieldByName('sepa_datum', sample.sepa_datum)
|
|
||||||
setFieldByName('sign_datum', sample.sign_datum)
|
|
||||||
|
|
||||||
// page3 fields
|
|
||||||
setFieldByName('page3_name', sample.page3_name)
|
|
||||||
setFieldByName('page3_vorname', sample.page3_vorname)
|
|
||||||
setFieldByName('page3_anschrift', sample.page3_anschrift)
|
|
||||||
setFieldByName('page3_telefon', sample.page3_telefon)
|
|
||||||
setFieldByName('page3_fax', sample.page3_fax)
|
|
||||||
setFieldByName('page3_email', sample.page3_email)
|
|
||||||
setFieldByName('page3_datum', sample.page3_datum)
|
|
||||||
|
|
||||||
// Debug: check which sample keys correspond to actual fields
|
|
||||||
try {
|
|
||||||
const names = form.getFields().map(f => f.getName().toLowerCase())
|
|
||||||
for (const key of Object.keys(sample)) {
|
|
||||||
const found = names.includes(key.toLowerCase())
|
|
||||||
console.log(`DEBUG: sample key='${key}' -> field present=${found}`)
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log('DEBUG: field presence check failed:', e.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debug: read back all field values after setting (before flattening)
|
|
||||||
try {
|
|
||||||
console.log('DEBUG: Field values after setting:')
|
|
||||||
for (const f of form.getFields()) {
|
|
||||||
const name = f.getName()
|
|
||||||
let val = null
|
|
||||||
try {
|
|
||||||
if (typeof f.getText === 'function') val = f.getText()
|
|
||||||
else if (typeof f.isChecked === 'function') val = f.isChecked()
|
|
||||||
else val = '(no getter)'
|
|
||||||
} catch (e) {
|
|
||||||
val = `(error reading: ${e.message})`
|
|
||||||
}
|
|
||||||
console.log(` ${name}: ${val}`)
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log('DEBUG: Could not read back field values:', e.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debug: print widget rectangles for relevant fields (SEPA and page3)
|
|
||||||
try {
|
|
||||||
const interesting = ['sepa_mitglied','sepa_kontoinhaber','sepa_strasse','sepa_plz_ort','sepa_bank','sepa_iban','sepa_bic','page3_name','page3_vorname','page3_anschrift','page3_telefon','page3_email']
|
|
||||||
for (const fname of interesting) {
|
|
||||||
const f = form.getFields().find(x => x.getName && x.getName().toLowerCase() === fname)
|
|
||||||
if (!f) { console.log(`DEBUG: no field object for ${fname}`); continue }
|
|
||||||
try {
|
|
||||||
// attempt to access widget rectangle via low-level acroField
|
|
||||||
const acro = f.acroField
|
|
||||||
const widgets = acro.getWidgets()
|
|
||||||
if (!widgets || widgets.length === 0) { console.log(`DEBUG: no widgets for ${fname}`); continue }
|
|
||||||
const rect = widgets[0].getRectangle()
|
|
||||||
console.log(`DEBUG: widget rect for ${fname}: ${JSON.stringify(rect)}`)
|
|
||||||
} catch (e) {
|
|
||||||
console.log(`DEBUG: cannot read widget rect for ${fname}: ${e.message}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log('DEBUG: widget rect inspection failed:', e.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define fallback drawing: draw visible text directly onto pages at widget rect positions
|
|
||||||
async function fallbackDraw() {
|
|
||||||
try {
|
|
||||||
const pages = pdfDoc.getPages()
|
|
||||||
// draw SEPA fields on page 2 (index 1)
|
|
||||||
const p2 = pages[1]
|
|
||||||
const sepaFields = ['sepa_mitglied','sepa_kontoinhaber','sepa_strasse','sepa_plz_ort','sepa_bank','sepa_iban','sepa_bic']
|
|
||||||
for (const fname of sepaFields) {
|
|
||||||
const f = form.getFields().find(x => x.getName && x.getName().toLowerCase() === fname)
|
|
||||||
if (!f) continue
|
|
||||||
try {
|
|
||||||
const widgets = f.acroField.getWidgets()
|
|
||||||
if (!widgets || widgets.length === 0) continue
|
|
||||||
const rect = widgets[0].getRectangle()
|
|
||||||
const text = (typeof f.getText === 'function') ? f.getText() : ''
|
|
||||||
if (text) {
|
|
||||||
p2.drawText(String(text), { x: rect.x + 2, y: rect.y + rect.height - 12, size: 11, font: helv })
|
|
||||||
console.log(`FALLBACK: drew ${fname} on page2 at ${rect.x},${rect.y}`)
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log(`FALLBACK: could not draw ${fname}: ${e.message}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw page3 fields on page 3 (index 2)
|
|
||||||
const p3 = pages[2]
|
|
||||||
const p3Fields = ['page3_name','page3_vorname','page3_anschrift','page3_telefon','page3_email']
|
|
||||||
for (const fname of p3Fields) {
|
|
||||||
const f = form.getFields().find(x => x.getName && x.getName().toLowerCase() === fname)
|
|
||||||
if (!f) continue
|
|
||||||
try {
|
|
||||||
const widgets = f.acroField.getWidgets()
|
|
||||||
if (!widgets || widgets.length === 0) continue
|
|
||||||
const rect = widgets[0].getRectangle()
|
|
||||||
const text = (typeof f.getText === 'function') ? f.getText() : ''
|
|
||||||
if (text) {
|
|
||||||
p3.drawText(String(text), { x: rect.x + 2, y: rect.y + rect.height - 12, size: 11, font: helv })
|
|
||||||
console.log(`FALLBACK: drew ${fname} on page3 at ${rect.x},${rect.y}`)
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log(`FALLBACK: could not draw ${fname}: ${e.message}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// write fallback copy
|
|
||||||
const fallbackBytes = await pdfDoc.save()
|
|
||||||
if (!fs.existsSync('temp')) fs.mkdirSync('temp')
|
|
||||||
fs.writeFileSync('temp/mitgliedschaft-sample-filled-fallback.pdf', fallbackBytes)
|
|
||||||
console.log('Wrote temp/mitgliedschaft-sample-filled-fallback.pdf')
|
|
||||||
} catch (e) {
|
|
||||||
console.log('FALLBACK drawing failed:', e.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update field appearances so text is visible, then flatten. Run fallback only when enabled.
|
|
||||||
try {
|
|
||||||
form.updateFieldAppearances(helv)
|
|
||||||
const outUnflattened = await pdfDoc.save()
|
|
||||||
if (!fs.existsSync('temp')) fs.mkdirSync('temp')
|
|
||||||
fs.writeFileSync('temp/mitgliedschaft-sample-filled-unflattened.pdf', outUnflattened)
|
|
||||||
form.flatten()
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('Could not update field appearances:', e.message)
|
|
||||||
const enableFallback = process.env.ENABLE_FALLBACK === '1' || (typeof sample.debug !== 'undefined' && sample.debug)
|
|
||||||
if (enableFallback) {
|
|
||||||
try { await fallbackDraw() } catch (err) { console.warn('Fallback draw failed:', err.message) }
|
|
||||||
try { form.flatten() } catch (err) { /* ignore */ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const out = await pdfDoc.save()
|
|
||||||
if (!fs.existsSync('temp')) fs.mkdirSync('temp')
|
|
||||||
fs.writeFileSync('temp/mitgliedschaft-sample-filled.pdf', out)
|
|
||||||
console.log('Wrote temp/mitgliedschaft-sample-filled.pdf')
|
|
||||||
}
|
|
||||||
|
|
||||||
fill().catch(e => { console.error(e); process.exit(1) })
|
|
||||||
@@ -10,7 +10,6 @@ function run(cmd) {
|
|||||||
async function main() {
|
async function main() {
|
||||||
const root = process.cwd()
|
const root = process.cwd()
|
||||||
run('node scripts/create-fillable-template.js')
|
run('node scripts/create-fillable-template.js')
|
||||||
run('node scripts/fill-sample-template.js')
|
|
||||||
const uploads = path.join(root, 'public', 'uploads')
|
const uploads = path.join(root, 'public', 'uploads')
|
||||||
const files = fs.existsSync(uploads) ? fs.readdirSync(uploads).filter(f => f.toLowerCase().endsWith('.pdf')) : []
|
const files = fs.existsSync(uploads) ? fs.readdirSync(uploads).filter(f => f.toLowerCase().endsWith('.pdf')) : []
|
||||||
console.log('Uploads PDFs:', files)
|
console.log('Uploads PDFs:', files)
|
||||||
|
|||||||
Reference in New Issue
Block a user