// Modules import createReport from 'docx-templates'; import fs, {writeFile} from 'fs'; import {mkdir} from 'node:fs/promises'; import path from 'path'; import replaceSpecialCharacters from "replace-special-characters"; import {parseString, Builder} from 'xml2js'; //////////////////// // Main // //////////////////// class DocCreator { constructor(log, objectData) { // Assign Log. this.log = log; // Assign general object data. this.objectData = objectData; // Get DateTime. this.today = new Date(); // Get config file and parse to json. this.configFile = fs.readFileSync('/resources/files/config/config.json') this.configJson = JSON.parse(this.configFile.toString()) // Choose the template for selected document type. switch (objectData.dokumenttyp) { case 'rp': this.documentInfo = { documentType: 'restaurierungsprotokolle', docTypeAbbr: 'rp', templateFile: 'rp-template.docx', } break; case 'lbb': this.documentInfo = { documentType: 'leihgabenbegleitblaetter', docTypeAbbr: 'lbb', templateFile: 'lbb-template.docx', } break; case 'a': this.documentInfo = { documentType: 'analysen', docTypeAbbr: 'a', templateFile: 'a-template.docx', } break; } // ObjectId normalisation. const normCharacterObjectId = replaceSpecialCharacters(objectData.inventarnummer); this.normObjectId = normCharacterObjectId.replace("__", "_"); // Title normalisation const replaceEszettTitle = objectData.titel.replace("ß", "-ss-"); let replaceUmlauteTitle = replaceEszettTitle.replace(/[^Ä]+/ig, "Ae"); replaceUmlauteTitle = replaceUmlauteTitle.replace(/[^ä]+/ig, "ae"); replaceUmlauteTitle = replaceUmlauteTitle.replace(/[^Ö]+/ig, "Oe"); replaceUmlauteTitle = replaceUmlauteTitle.replace(/[^ö]+/ig, "oe"); replaceUmlauteTitle = replaceUmlauteTitle.replace(/[^Ü]+/ig, "Ue"); replaceUmlauteTitle = replaceUmlauteTitle.replace(/[^ü]+/ig, "ue"); const normCharacterTitle = replaceSpecialCharacters(replaceUmlauteTitle); const normSingleSpaceTitle = normCharacterTitle.replace("__", "_"); const normSpacingTitle = normSingleSpaceTitle.replace(/[^A-Z0-9\-]+/ig, "_"); this.normTitle = normSpacingTitle.slice(0, 50); const folderName = this.normObjectId + '__' + this.normTitle this.objectPath = path.join(this.configJson.rootDir, folderName); this.documentPath = path.join(this.objectPath, this.documentInfo.documentType, objectData.datum); this.filename = this.normObjectId + '__' + this.normTitle + '__' + this.objectData.datum + '__' + this.objectData.dokumenttyp; this.filenameWithExtension = this.filename + '.docx' this.temporaryWorkDirPath = path.join(this.objectPath, 'werkstatt'); } // Fills the docx template. async fillTemplate() { // Variables let buffer; let configJson // Create docx document if there was a response. if (this.objectData.httpStatus === 200) { try { // Read template. const template = fs.readFileSync(path.join('/resources/files/templates/', this.documentInfo.templateFile)); // Create report. buffer = await createReport({ template, data: { inventarnummer: this.objectData.inventarnummer ? this.objectData.inventarnummer : 'unbekannt', titel: this.objectData.titel ? this.objectData.titel : 'unbekannt', hersteller: this.objectData.hersteller ? this.objectData.hersteller : 'unbekannt', herstellungsort: this.objectData.herstellungsort ? this.objectData.herstellungsort : 'unbekannt', herstellungsdatum: this.objectData.herstellungsdatum ? this.objectData.herstellungsdatum : 'unbekannt', materialTechnik: this.objectData.materialTechnik ? this.objectData.materialTechnik : 'unbekannt', masse: this.objectData.masse ? this.objectData.masse : 'unbekannt' } }); } catch (err) { // Set error log. this.log = { ...this.log, status: 'red', message: 'Konnte Template nicht erstellen: ' + err, tip: 'Ist das Template vorhanden?', }; return this.log } try { const createDocumentPath = await mkdir(this.documentPath, {recursive: true}); const createTemporaryWorkDirPath = await mkdir(this.temporaryWorkDirPath, {recursive: true}); } catch (err) { // Set error log. this.log = { ...this.log, status: 'red', message: 'Konnte den Pfad nicht erstellen' + err, tip: 'Bestehen Schreibrechte auf dem Ordner?' } return this.log } // Write document to disk. if (buffer) { fs.writeFileSync(path.join(this.documentPath, this.filenameWithExtension), buffer) this.log = { ...this.log, status: 'green', message: 'Dokument erstellt', }; } } else { this.log = { status: 'red', message: 'Fehler bei der Kommunikation mit dem Objektkatalog', code: this.objectData.httpStatus, tip: 'Ist die Inventarnummer richtig?', }; } return this.log; } async createMetsMods() { const metsModsString = ` ${process.env.REACT_APP_NAME} v${process.env.REACT_APP_VERSION} ${this.objectData.inventarnummer} ${this.objectData.titel} ${this.objectData.herstellungsdatum} ${this.objectData.herstellungsort} cre ${this.objectData.herstellungsort} ${this.objectData.herstellungsort} ${this.objectData.masse} ` const metModsJson = { 'mets:mets': { $: { 'xmlns:mets': "http://www.loc.gov/METS/", 'xmlns:xlink': "http://www.w3.org/1999/xlink", 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance", 'xsi:schemaLocation': "info:lc/xmlns/premis-v2 http://www.loc.gov/standards/premis/v2/premis-v2-0.xsd " + "http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-6.xsd " + "http://www.loc.gov/METS/ http://www.loc.gov/standards/mets/version17/mets.v1-7.xsd " + "http://www.loc.gov/mix/v10 http://www.loc.gov/standards/mix/mix10/mix10.xsd" }, 'mets:metsHdr': { $: { // Creation date of the mets/mods xml. 'createDate': this.today // Should be w3ctdf format: YYYY-MM-DDThh:mm:ssTZD }, 'mets:agent': { // App, which created the xml document $: { 'type': 'other', 'otherType': 'software', 'role': 'creator' }, 'mets:name': { // App name and version _: `${process.env.REACT_APP_NAME} v${process.env.REACT_APP_VERSION}` } } }, 'mets:fileSec': { 'mets:fielGrp': { $: { // Documenttype 'use': `${this.documentInfo.documentType}` }, 'mets:file': { // Phyical file $: { 'id': `file__${this.filename}`, 'mimeType': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }, 'mets:FLocat': { // Physical location - here in same folder $: { 'locType': 'other', 'otherLocType': 'file', 'xlink:href': `${this.filenameWithExtension}` } } } } }, 'mets:structMap': [ { // These are solo documents only, this may be inappropriate. $: { // Physical structure. 'type': 'physical' }, 'mets:div': { $: { // Documenttype and id. 'type': `${this.documentInfo.docTypeAbbr}`, // since we have only one document, id and dmdid are static. 'id': `phys_00`, 'dmdid': 'dmdphys_00' }, 'mets:fptr': { $: { // File id from above 'fileId': `file__${this.filename}` } } } }, { // These are solo documents only, this may be inappropriate. $: { // Physical structure. 'type': 'logical' }, 'mets:div': { $: { // Documenttype and id. 'type': `${this.documentInfo.docTypeAbbr}`, // since we have only one document, id and dmdid are static. 'id': `phys_00`, 'dmdid': 'dmdphys_00' }, 'mets:fptr': { $: { // File id from above 'fileId': `file__${this.filename}` } } } }], 'mets:dmdSec': { $: { // Since we have only one document, dmdlog is static 'id': `dmdlog_00` } , 'mets:mdWrap': { $: { 'mdType': 'mods' } , 'mets:xmlData': { 'mods:mods': { // Object properties as found at https://objektkatalog.gnm.de. $: { 'xmlns:mods': 'http://www.loc.gov/mods/v3' } , 'mods:recordInfo': { 'mods:recordIdentifier': { // ObjectId. $: { 'source': 'https://objektkatalag.gnm.de' } , _: `${this.objectData.inventarnummer}` } } , 'mods:titleInfo': { // Title. 'mods:title': { _: `${this.objectData.titel}` } } , 'mods:originInfo': { // Creation date. 'mods_dateIssued': { $: { 'encoding': 'w3cdtf', // W3C Date and Time, should be YYYY-MM-DDThh:mm:ssTZD 'keyDate': 'yes' } , _: `${this.objectData.herstellungsdatum}` } , 'mods:place': { // Creation place 'mods:placeTerm': { $: { 'type': 'text' } , _: `${this.objectData.herstellungsort}` } } } , 'mods:name': { // Creator. $: { 'type': 'personal' } , 'mods:role': { 'mods:roleTerm': { $: { 'authority': 'marcrelator', 'type': 'code' } , _: 'cre' } } , 'mods:namePart': { _: this.objectData.hersteller } , 'mods:displayForm': { _: this.objectData.hersteller } } , 'mods:physicalDescription': { 'mods:form': { $: { 'type': 'Material and Technique', 'lang': 'de' } } , 'mods:extent': { _: `${this.objectData.masse}` } } } } } } } } let metModsXml parseString(metsModsString, {trim: true}, function (err, result) { metModsXml = result; } ); console.log(metModsXml, 'from string'); const builder = new Builder() metModsXml = builder.buildObject(metModsJson); console.log(metModsXml, 'from Json') const fileName = `.metsMods__${this.normObjectId}__${this.normTitle}.xml` fs.writeFileSync(path.join(this.documentPath,fileName),metModsXml.toString(), function (err) { if (err) { console.log(err); } else { console.log("The file was saved!"); } } ) return true; } } export {DocCreator};