diff --git a/package-lock.json b/package-lock.json index 57a5acc..2402cb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "nodemailer": "^7.0.9", "nuxt": "^4.1.3", "pdf-parse": "^2.4.5", + "pdfjs-dist": "^5.4.296", "pinia": "^3.0.3", "vue": "^3.5.22" }, diff --git a/package.json b/package.json index c4e0fe0..949948e 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "nodemailer": "^7.0.9", "nuxt": "^4.1.3", "pdf-parse": "^2.4.5", + "pdfjs-dist": "^5.4.296", "pinia": "^3.0.3", "vue": "^3.5.22" }, diff --git a/server/api/cms/satzung-upload.post.js b/server/api/cms/satzung-upload.post.js index ecad0ec..052f095 100644 --- a/server/api/cms/satzung-upload.post.js +++ b/server/api/cms/satzung-upload.post.js @@ -1,6 +1,10 @@ import multer from 'multer' import fs from 'fs/promises' import path from 'path' +import * as pdfjsLib from 'pdfjs-dist' + +// PDF.js Worker konfigurieren +pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker.min.js' // Handle both dev and production paths const getDataPath = (filename) => { @@ -64,25 +68,22 @@ export default defineEventHandler(async (event) => { }) } - // Für jetzt: Satzungsinhalt als Platzhalter bis PDF-Parsing implementiert ist - const htmlContent = ` -

§ 1 Name und Sitz

-

Der Verein führt den Namen "Harheimer Tischtennis-Club" und hat seinen Sitz in Harheim.

- -

§ 2 Zweck des Vereins

-

Der Verein verfolgt ausschließlich und unmittelbar gemeinnützige Zwecke im Sinne des Abschnitts "Steuerbegünstigte Zwecke" der Abgabenordnung.

- -

§ 3 Mitgliedschaft

-

Mitglied des Vereins kann jede natürliche Person werden, die die Ziele des Vereins unterstützt.

- -

§ 4 Beiträge

-

Die Mitglieder zahlen Beiträge nach Maßgabe der Beitragsordnung.

- -

§ 5 Vorstand

-

Der Vorstand besteht aus dem Vorsitzenden, dem stellvertretenden Vorsitzenden, dem Kassenwart und dem Schriftführer.

- -

Hinweis: Dies ist ein Platzhalter-Inhalt. Der vollständige Satzungstext wird automatisch aus der hochgeladenen PDF-Datei extrahiert, sobald das PDF-Parsing implementiert ist.

- ` + // PDF-Text extrahieren mit PDF.js + const pdfBuffer = await fs.readFile(file.path) + const pdfData = await pdfjsLib.getDocument({ data: pdfBuffer }).promise + + let fullText = '' + + // Alle Seiten durchgehen + for (let pageNum = 1; pageNum <= pdfData.numPages; pageNum++) { + const page = await pdfData.getPage(pageNum) + const textContent = await page.getTextContent() + const pageText = textContent.items.map(item => item.str).join(' ') + fullText += pageText + '\n' + } + + // Text in HTML-Format konvertieren + const htmlContent = convertTextToHtml(fullText) // Config aktualisieren const configPath = getDataPath('config.json') @@ -110,17 +111,47 @@ export default defineEventHandler(async (event) => { } }) -// TODO: PDF-Parsing-Funktion später implementieren -// function convertTextToHtml(text) { -// // Einfache Text-zu-HTML-Konvertierung -// let html = text -// .replace(/\n\n+/g, '

') // Absätze -// .replace(/\n/g, '
') // Zeilenumbrüche -// .replace(/^(.+)$/gm, '

$1

') // Alle Zeilen in Paragraphen -// -// // Überschriften erkennen (einfache Heuristik) -// html = html.replace(/

(§\s*\d+.*?)<\/p>/g, '

$1

') -// html = html.replace(/

(\d+\.\s+.*?)<\/p>/g, '

$1

') -// -// return `

Satzung

${html}` -// } +// PDF-Text zu HTML konvertieren +function convertTextToHtml(text) { + // Text bereinigen und strukturieren + let html = text + .replace(/\r\n/g, '\n') // Windows-Zeilenumbrüche normalisieren + .replace(/\r/g, '\n') // Mac-Zeilenumbrüche normalisieren + .replace(/\n\s*\n/g, '\n\n') // Mehrfache Zeilenumbrüche reduzieren + .trim() + + // Überschriften erkennen und formatieren + html = html.replace(/^(Vereinssatzung|Satzung)$/gm, '

$1

') + html = html.replace(/^(§\s*\d+[^§\n]*)$/gm, '

$1

') + + // Absätze erstellen + html = html.split('\n\n').map(paragraph => { + paragraph = paragraph.trim() + if (!paragraph) return '' + + // Überschriften nicht als Paragraphen behandeln + if (paragraph.match(/^/) || paragraph.match(/^§\s*\d+/)) { + return paragraph + } + + // Listen erkennen + if (paragraph.includes('•') || paragraph.includes('-') || paragraph.match(/^\d+\./)) { + const listItems = paragraph.split(/\n/).map(item => { + item = item.trim() + if (item.match(/^[•\-]\s/) || item.match(/^\d+\.\s/)) { + return `
  • ${item.replace(/^[•\-]\s/, '').replace(/^\d+\.\s/, '')}
  • ` + } + return `
  • ${item}
  • ` + }).join('') + return `` + } + + // Normale Absätze + return `

    ${paragraph.replace(/\n/g, '
    ')}

    ` + }).join('\n') + + // Mehrfache Zeilenumbrüche entfernen + html = html.replace(/\n{3,}/g, '\n\n') + + return html +}