new(basic.gblib): FILL keyword can now template images and AS IMAGE can convert a DOCX to a PNG.
This commit is contained in:
parent
0fa7a828a3
commit
74e7a6e795
2 changed files with 46 additions and 33 deletions
|
@ -95,8 +95,8 @@
|
||||||
"core-js": "3.26.1",
|
"core-js": "3.26.1",
|
||||||
"data-forge": "1.9.6",
|
"data-forge": "1.9.6",
|
||||||
"date-diff": "1.0.2",
|
"date-diff": "1.0.2",
|
||||||
"docximager": "^0.0.4",
|
"docximager": "0.0.4",
|
||||||
"docxtemplater": "3.32.4",
|
"docxtemplater": "3.9.7",
|
||||||
"dotenv-extended": "2.9.0",
|
"dotenv-extended": "2.9.0",
|
||||||
"exceljs": "4.3.0",
|
"exceljs": "4.3.0",
|
||||||
"express": "4.18.2",
|
"express": "4.18.2",
|
||||||
|
@ -120,6 +120,7 @@
|
||||||
"node-tesseract-ocr": "2.2.1",
|
"node-tesseract-ocr": "2.2.1",
|
||||||
"npm": "9.1.2",
|
"npm": "9.1.2",
|
||||||
"open": "8.4.0",
|
"open": "8.4.0",
|
||||||
|
"open-docxtemplater-image-module": "^1.0.3",
|
||||||
"pdf-extraction": "1.0.2",
|
"pdf-extraction": "1.0.2",
|
||||||
"pdf-to-png-converter": "^2.7.1",
|
"pdf-to-png-converter": "^2.7.1",
|
||||||
"pdfkit": "0.13.0",
|
"pdfkit": "0.13.0",
|
||||||
|
|
|
@ -55,6 +55,7 @@ import { DocxImager } from 'docximager';
|
||||||
import { pdfToPng, PngPageOutput } from 'pdf-to-png-converter';
|
import { pdfToPng, PngPageOutput } from 'pdf-to-png-converter';
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
import apply from 'async/apply';
|
import apply from 'async/apply';
|
||||||
|
import ImageModule from 'open-docxtemplater-image-module';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fileoverview General Bots server core.
|
* @fileoverview General Bots server core.
|
||||||
|
@ -1404,10 +1405,6 @@ export class SystemKeywords {
|
||||||
// Loads the file as binary content.
|
// Loads the file as binary content.
|
||||||
|
|
||||||
let zip = new PizZip(buf);
|
let zip = new PizZip(buf);
|
||||||
let doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true });
|
|
||||||
if (localName.endsWith('.pptx')) {
|
|
||||||
doc.attachModule(pptxTemplaterModule);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace image path on all elements of data.
|
// Replace image path on all elements of data.
|
||||||
|
|
||||||
|
@ -1418,10 +1415,15 @@ export class SystemKeywords {
|
||||||
const traverseDataToInjectImageUrl = async o => {
|
const traverseDataToInjectImageUrl = async o => {
|
||||||
for (var i in o) {
|
for (var i in o) {
|
||||||
let value = o[i];
|
let value = o[i];
|
||||||
let key = i;
|
|
||||||
|
if (value && value.gbarray){
|
||||||
|
o.shift();
|
||||||
|
value = o[i];
|
||||||
|
}
|
||||||
|
|
||||||
for (const kind of ['png', 'jpg', 'jpeg']) {
|
for (const kind of ['png', 'jpg', 'jpeg']) {
|
||||||
if (value.endsWith && value.endsWith(`.${kind}`)) {
|
if (value.endsWith && value.endsWith(`.${kind}`)) {
|
||||||
|
|
||||||
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(this.min);
|
const { baseUrl, client } = await GBDeployer.internalGetDriveClient(this.min);
|
||||||
|
|
||||||
path = urlJoin(gbaiName, `${botId}.gbdrive`);
|
path = urlJoin(gbaiName, `${botId}.gbdrive`);
|
||||||
|
@ -1429,24 +1431,27 @@ export class SystemKeywords {
|
||||||
path = '/' + urlJoin(path, Path.dirname(value));
|
path = '/' + urlJoin(path, Path.dirname(value));
|
||||||
value = Path.basename(value);
|
value = Path.basename(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ref = await this.internalGetDocument(client, baseUrl, path, value);
|
const ref = await this.internalGetDocument(client, baseUrl, path, value);
|
||||||
let url = ref['@microsoft.graph.downloadUrl'];
|
let url = ref['@microsoft.graph.downloadUrl'];
|
||||||
const imageName = Path.join('work', gbaiName, 'cache', `tmp${GBAdminService.getRndReadableIdentifier()}.png`);
|
const imageName = Path.join(
|
||||||
|
'work',
|
||||||
|
gbaiName,
|
||||||
|
'cache',
|
||||||
|
`tmp${GBAdminService.getRndReadableIdentifier()}-${value}.png`
|
||||||
|
);
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
const buf = Buffer.from(await response.arrayBuffer());
|
const buf = Buffer.from(await response.arrayBuffer());
|
||||||
Fs.writeFileSync(imageName, buf, { encoding: null });
|
Fs.writeFileSync(imageName, buf, { encoding: null });
|
||||||
|
|
||||||
const getNormalSize = ({ width, height, orientation }) => {
|
const getNormalSize = ({ width, height, orientation }) => {
|
||||||
return (orientation || 0) >= 5 ? { width: height, height: width } : { width, height };
|
return (orientation || 0) >= 5 ? [ height, width ] : [ width, height];
|
||||||
};
|
};
|
||||||
|
|
||||||
const size = getNormalSize(await sharp(buf).metadata());
|
const size = getNormalSize(await sharp(buf).metadata());
|
||||||
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', Path.basename(imageName));
|
url = urlJoin(GBServer.globals.publicAddress, min.botId, 'cache', Path.basename(imageName));
|
||||||
images[index++] = url;
|
images[index++] = {url: url, size:size, buf: buf} ;
|
||||||
|
|
||||||
const imageToken = `{{insert_image img${index} ${kind} ${size.height} ${size.width} }}`;
|
|
||||||
o[key] = imageToken;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (o[i] !== null && typeof o[i] == 'object') {
|
if (o[i] !== null && typeof o[i] == 'object') {
|
||||||
|
@ -1455,28 +1460,35 @@ export class SystemKeywords {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
await traverseDataToInjectImageUrl(data);
|
let indexImage = 0;
|
||||||
doc.render(data);
|
var opts = {
|
||||||
|
fileType: 'docx',
|
||||||
|
centered: false,
|
||||||
|
getImage: (tagValue, tagName) => {
|
||||||
|
return images[indexImage].buf;
|
||||||
|
|
||||||
|
},
|
||||||
|
getSize: (img, tagValue, tagName) => {
|
||||||
|
return images[indexImage].size;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let doc = new Docxtemplater();
|
||||||
|
doc.setOptions({ paragraphLoop: true, linebreaks: true });
|
||||||
|
doc.loadZip(zip);
|
||||||
|
if (localName.endsWith('.pptx')) {
|
||||||
|
doc.attachModule(pptxTemplaterModule);
|
||||||
|
}
|
||||||
|
doc.attachModule(new ImageModule(opts));
|
||||||
|
|
||||||
|
await traverseDataToInjectImageUrl(data);
|
||||||
|
doc
|
||||||
|
.setData(data)
|
||||||
|
.render();
|
||||||
|
|
||||||
buf = doc.getZip().generate({ type: 'nodebuffer', compression: 'DEFLATE' });
|
buf = doc.getZip().generate({ type: 'nodebuffer', compression: 'DEFLATE' });
|
||||||
Fs.writeFileSync(localName, buf, { encoding: null });
|
Fs.writeFileSync(localName, buf, { encoding: null });
|
||||||
|
|
||||||
if (images) {
|
|
||||||
// Replaces images within the document.
|
|
||||||
|
|
||||||
let docxImager = new DocxImager();
|
|
||||||
await docxImager.load(localName);
|
|
||||||
let i = 0;
|
|
||||||
await CollectionUtil.asyncForEach(images, async image => {
|
|
||||||
if (i>0)return; //////////////////////////////
|
|
||||||
const url = images[i++];
|
|
||||||
const json = JSON.parse(`{"img${i}": "${url}"}`);
|
|
||||||
await docxImager.insertImage(json);
|
|
||||||
});
|
|
||||||
await docxImager.save(localName);
|
|
||||||
buf = Fs.readFileSync(localName, 'binary');
|
|
||||||
}
|
|
||||||
|
|
||||||
return { localName: localName, url: url, data: buf };
|
return { localName: localName, url: url, data: buf };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue