Compare commits
No commits in common. "bec4c8bf4cc62206ab5d75ef969e0ca4c37d5bd6" and "e8c9a307ab4b917fe180ed62529276a344a292f7" have entirely different histories.
bec4c8bf4c
...
e8c9a307ab
@ -51,14 +51,6 @@ export const hasPermission = async (user, objectType, action) => {
|
||||
|
||||
export const checkPermissions = (objectType, action) => async (req, res, next) => {
|
||||
try {
|
||||
if (req.user?._objectType == 'host') {
|
||||
if (
|
||||
(objectType === 'documentTemplate' && action === 'design') ||
|
||||
(objectType === 'file' && action === 'download')
|
||||
) {
|
||||
return next();
|
||||
}
|
||||
}
|
||||
const allowed = await hasPermission(req.user, objectType, action);
|
||||
if (!allowed) {
|
||||
return res.status(403).json({ error: 'Forbidden', code: 'FORBIDDEN' });
|
||||
|
||||
@ -25,31 +25,6 @@ const documentSizeSchema = new Schema(
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
printPadding: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
paddingLeft: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
},
|
||||
paddingRight: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
},
|
||||
paddingTop: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
},
|
||||
paddingBottom: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
@ -63,7 +63,7 @@ const isAuthenticated = async (req, res, next) => {
|
||||
try {
|
||||
const session = await getSession(token);
|
||||
if (session && session.expiresAt > Date.now()) {
|
||||
req.user = { ...session.user, _objectType: 'user' };
|
||||
req.user = session.user;
|
||||
req.session = session;
|
||||
return next();
|
||||
}
|
||||
@ -71,7 +71,7 @@ const isAuthenticated = async (req, res, next) => {
|
||||
// Try email-render JWT (short-lived token for Puppeteer email notifications)
|
||||
const user = await lookupUserByToken(token);
|
||||
if (user) {
|
||||
req.user = { ...user, _objectType: 'user' };
|
||||
req.user = user;
|
||||
req.session = { user };
|
||||
return next();
|
||||
}
|
||||
@ -85,7 +85,6 @@ const isAuthenticated = async (req, res, next) => {
|
||||
if (hostId && authCode) {
|
||||
const host = await getObject({ model: hostModel, id: hostId });
|
||||
if (host && host.authCode === authCode) {
|
||||
req.user = { ...host, _objectType: 'host' };
|
||||
return next();
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,32 +5,8 @@ import { getFilter, convertPropertiesString, getSort } from '../../utils.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
const listAllowedFilters = [
|
||||
'name',
|
||||
'width',
|
||||
'height',
|
||||
'printPadding',
|
||||
'paddingLeft',
|
||||
'paddingRight',
|
||||
'paddingTop',
|
||||
'paddingBottom',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'_reference',
|
||||
];
|
||||
const listAllowedSorters = [
|
||||
'name',
|
||||
'width',
|
||||
'height',
|
||||
'infiniteHeight',
|
||||
'printPadding',
|
||||
'paddingLeft',
|
||||
'paddingRight',
|
||||
'paddingTop',
|
||||
'paddingBottom',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
];
|
||||
const listAllowedFilters = ['name', 'width', 'height', 'createdAt', 'updatedAt', '_reference'];
|
||||
const listAllowedSorters = ['name', 'width', 'height', 'infiniteHeight', 'createdAt', 'updatedAt'];
|
||||
const propertiesAllowedFilters = [];
|
||||
import {
|
||||
listDocumentSizesRouteHandler,
|
||||
|
||||
@ -77,34 +77,13 @@ describe('Document Size Service Route Handlers', () => {
|
||||
|
||||
describe('newDocumentSizeRouteHandler', () => {
|
||||
it('should create a new document size', async () => {
|
||||
req.body = {
|
||||
name: 'Letter',
|
||||
width: 216,
|
||||
height: 279,
|
||||
infiniteHeight: false,
|
||||
printPadding: false,
|
||||
paddingLeft: 0,
|
||||
paddingRight: 0,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
};
|
||||
req.body = { name: 'Letter', width: 216, height: 279 };
|
||||
const mockSize = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockSize);
|
||||
|
||||
await newDocumentSizeRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
newData: expect.objectContaining({
|
||||
name: 'Letter',
|
||||
printPadding: false,
|
||||
paddingLeft: 0,
|
||||
paddingRight: 0,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
}),
|
||||
})
|
||||
);
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockSize);
|
||||
});
|
||||
});
|
||||
|
||||
@ -113,7 +113,7 @@ describe('Document Template Service Route Handlers', () => {
|
||||
'<Text>Hello</Text>',
|
||||
{ name: 'Test' },
|
||||
1,
|
||||
{ padding: true },
|
||||
{},
|
||||
true
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockPreview);
|
||||
@ -155,34 +155,12 @@ describe('Document Template Service Route Handlers', () => {
|
||||
'<Text>Hello</Text>',
|
||||
{ name: 'Test' },
|
||||
'pdf',
|
||||
{ padding: true }
|
||||
{}
|
||||
);
|
||||
expect(res.set).toHaveBeenCalledWith('Content-Type', 'application/pdf');
|
||||
expect(res.send).toHaveBeenCalledWith(pdf);
|
||||
});
|
||||
|
||||
it('passes padding false when requested by the caller', async () => {
|
||||
req.params.id = 'template-1';
|
||||
req.query = { type: 'pdf', padding: 'false' };
|
||||
req.body = { object: { name: 'Test' } };
|
||||
templateManager.renderDownload.mockResolvedValue({
|
||||
type: 'pdf',
|
||||
mime: 'application/pdf',
|
||||
extension: 'pdf',
|
||||
buffers: [Buffer.from('pdf-data')],
|
||||
});
|
||||
|
||||
await downloadDocumentTemplateRouteHandler(req, res);
|
||||
|
||||
expect(templateManager.renderDownload).toHaveBeenCalledWith(
|
||||
'template-1',
|
||||
undefined,
|
||||
{ name: 'Test' },
|
||||
'pdf',
|
||||
{ padding: false }
|
||||
);
|
||||
});
|
||||
|
||||
it('should return base64 images when multiple pages are rendered', async () => {
|
||||
req.params.id = 'template-1';
|
||||
req.query = { type: 'png' };
|
||||
|
||||
@ -116,11 +116,6 @@ export const editDocumentSizeRouteHandler = async (req, res) => {
|
||||
width: req.body.width,
|
||||
height: req.body.height,
|
||||
infiniteHeight: req.body.infiniteHeight,
|
||||
printPadding: req.body.printPadding,
|
||||
paddingLeft: req.body.paddingLeft,
|
||||
paddingRight: req.body.paddingRight,
|
||||
paddingTop: req.body.paddingTop,
|
||||
paddingBottom: req.body.paddingBottom,
|
||||
};
|
||||
// Create audit log before updating
|
||||
const result = await editObject({
|
||||
@ -148,11 +143,6 @@ export const newDocumentSizeRouteHandler = async (req, res) => {
|
||||
width: req.body.width,
|
||||
height: req.body.height,
|
||||
infiniteHeight: req.body.infiniteHeight,
|
||||
printPadding: req.body.printPadding,
|
||||
paddingLeft: req.body.paddingLeft,
|
||||
paddingRight: req.body.paddingRight,
|
||||
paddingTop: req.body.paddingTop,
|
||||
paddingBottom: req.body.paddingBottom,
|
||||
};
|
||||
const result = await newObject({
|
||||
model: documentSizeModel,
|
||||
|
||||
@ -20,27 +20,6 @@ import { formatTemplateContent } from '../../templates/templateformatter.js';
|
||||
const logger = log4js.getLogger('Document Templates');
|
||||
logger.level = config.server.logLevel;
|
||||
|
||||
function parseOptionalBoolean(value) {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
return undefined;
|
||||
}
|
||||
if (value === true || value === false) {
|
||||
return value;
|
||||
}
|
||||
const lower = String(value).trim().toLowerCase();
|
||||
if (lower === 'true' || lower === '1') {
|
||||
return true;
|
||||
}
|
||||
if (lower === 'false' || lower === '0') {
|
||||
return false;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getPaddingOption(req, defaultValue = true) {
|
||||
return parseOptionalBoolean(req.body?.padding ?? req.query?.padding) ?? defaultValue;
|
||||
}
|
||||
|
||||
export const listDocumentTemplatesRouteHandler = async (
|
||||
req,
|
||||
res,
|
||||
@ -314,7 +293,6 @@ export const previewDocumentTemplateRouteHandler = async (req, res) => {
|
||||
const content = req.body?.content;
|
||||
const testObject = req.body?.testObject || req.body?.object || {};
|
||||
const scale = req.body?.scale ?? 1;
|
||||
const padding = getPaddingOption(req, true);
|
||||
|
||||
logger.debug(`Previewing document template with ID: ${id}`);
|
||||
|
||||
@ -323,7 +301,7 @@ export const previewDocumentTemplateRouteHandler = async (req, res) => {
|
||||
content,
|
||||
testObject,
|
||||
scale,
|
||||
{ padding },
|
||||
{},
|
||||
true
|
||||
);
|
||||
|
||||
@ -342,9 +320,7 @@ export const downloadDocumentTemplateRouteHandler = async (req, res) => {
|
||||
const data = req.body?.object || req.body?.testObject || {};
|
||||
const width = req.body?.width || req.query.width;
|
||||
const filename = req.body?.filename || req.query.filename || 'document';
|
||||
const options = {
|
||||
padding: getPaddingOption(req, true),
|
||||
};
|
||||
const options = {};
|
||||
if (width) {
|
||||
options.width = Number(width);
|
||||
}
|
||||
|
||||
@ -59,25 +59,4 @@ describe('formatTemplateContent', () => {
|
||||
expect(result.content).not.toMatch(/\(\s+<%/);
|
||||
expect(result.content).not.toMatch(/%>\s+\)/);
|
||||
});
|
||||
|
||||
it('should not add a space next to a colon before EJS output', () => {
|
||||
const input =
|
||||
'<Barcode format="code128" height="33px" barcodeWidth="3">INV: <%= _reference %>\n </Barcode>';
|
||||
const result = formatTemplateContent(input);
|
||||
|
||||
expect(result.content).toBe(
|
||||
'<Barcode format="code128" height="33px" barcodeWidth="3">INV:<%= _reference %></Barcode>'
|
||||
);
|
||||
});
|
||||
|
||||
it('should keep barcode content and the closing tag on one line', () => {
|
||||
const input =
|
||||
'<Barcode format="code128" height="33px" barcodeWidth="3">INV:<%= _reference %></Barcode>';
|
||||
const result = formatTemplateContent(input);
|
||||
|
||||
expect(result.content).toBe(
|
||||
'<Barcode format="code128" height="33px" barcodeWidth="3">INV:<%= _reference %></Barcode>'
|
||||
);
|
||||
expect(result.content).not.toMatch(/%>\s*\n\s*<\/Barcode>/);
|
||||
});
|
||||
});
|
||||
|
||||
@ -91,51 +91,11 @@ jest.unstable_mockModule('../../config.js', () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const { TemplateManager, resolveDocumentPadding } = await import('../templatemanager.js');
|
||||
const { TemplateManager } = await import('../templatemanager.js');
|
||||
const { getObject } = await import('../../database/database.js');
|
||||
const ejs = (await import('ejs')).default;
|
||||
const { generatePDF } = await import('../pdffactory.js');
|
||||
|
||||
describe('resolveDocumentPadding', () => {
|
||||
const paddedSize = {
|
||||
printPadding: false,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 8,
|
||||
paddingTop: 6,
|
||||
paddingBottom: 4,
|
||||
};
|
||||
|
||||
it('does not apply padding unless requested or printPadding is true', () => {
|
||||
expect(resolveDocumentPadding(paddedSize, false)).toEqual({
|
||||
applyPadding: false,
|
||||
paddingLeft: 0,
|
||||
paddingRight: 0,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('applies padding when requested', () => {
|
||||
expect(resolveDocumentPadding(paddedSize, true)).toEqual({
|
||||
applyPadding: true,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 8,
|
||||
paddingTop: 6,
|
||||
paddingBottom: 4,
|
||||
});
|
||||
});
|
||||
|
||||
it('applies padding when printPadding is true even if not requested', () => {
|
||||
expect(resolveDocumentPadding({ ...paddedSize, printPadding: true }, false)).toEqual({
|
||||
applyPadding: true,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 8,
|
||||
paddingTop: 6,
|
||||
paddingBottom: 4,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('TemplateManager', () => {
|
||||
let templateManager;
|
||||
|
||||
@ -201,87 +161,6 @@ describe('TemplateManager', () => {
|
||||
expect(generatePDF).toHaveBeenCalled();
|
||||
expect(result.pdf).toBeDefined();
|
||||
});
|
||||
|
||||
it('adds padding to page size when padding is requested', async () => {
|
||||
getObject.mockResolvedValue({
|
||||
documentSize: {
|
||||
width: 100,
|
||||
height: 50,
|
||||
infiniteHeight: false,
|
||||
printPadding: false,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
paddingTop: 5,
|
||||
paddingBottom: 5,
|
||||
},
|
||||
global: false,
|
||||
objectType: 'printer',
|
||||
});
|
||||
|
||||
await templateManager.renderPDF('temp-id', 'content', {}, { padding: true });
|
||||
|
||||
expect(generatePDF).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
expect.objectContaining({
|
||||
width: 120,
|
||||
height: 60,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('adds padding when printPadding is true even if padding is false', async () => {
|
||||
getObject.mockResolvedValue({
|
||||
documentSize: {
|
||||
width: 100,
|
||||
height: 50,
|
||||
infiniteHeight: false,
|
||||
printPadding: true,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
paddingTop: 5,
|
||||
paddingBottom: 5,
|
||||
},
|
||||
global: false,
|
||||
objectType: 'printer',
|
||||
});
|
||||
|
||||
await templateManager.renderPDF('temp-id', 'content', {}, { padding: false });
|
||||
|
||||
expect(generatePDF).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
expect.objectContaining({
|
||||
width: 120,
|
||||
height: 60,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps the original page size when padding is not applied', async () => {
|
||||
getObject.mockResolvedValue({
|
||||
documentSize: {
|
||||
width: 100,
|
||||
height: 50,
|
||||
infiniteHeight: false,
|
||||
printPadding: false,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 10,
|
||||
paddingTop: 5,
|
||||
paddingBottom: 5,
|
||||
},
|
||||
global: false,
|
||||
objectType: 'printer',
|
||||
});
|
||||
|
||||
await templateManager.renderPDF('temp-id', 'content', {}, { padding: false });
|
||||
|
||||
expect(generatePDF).toHaveBeenCalledWith(
|
||||
expect.any(String),
|
||||
expect.objectContaining({
|
||||
width: 100,
|
||||
height: 50,
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('renderDownload', () => {
|
||||
|
||||
@ -18,22 +18,18 @@
|
||||
}
|
||||
|
||||
.previewWrapper {
|
||||
width: <%= (scaledPageWidth) || (scaledWidth) || '50mm' %>;
|
||||
height: <%= (scaledPageHeight) || (scaledHeight) || '50mm' %>;
|
||||
width: <%= (scaledWidth) || '50mm' %>;
|
||||
height: <%= (scaledHeight) || '50mm' %>;
|
||||
}
|
||||
.previewDocument {
|
||||
width: <%= (width) || '50mm' %>;
|
||||
height: <%= (height) || '50mm' %>;
|
||||
padding: <%= (paddingTop) || '0mm' %> <%= (paddingRight) || '0mm' %> <%= (paddingBottom) || '0mm' %> <%= (paddingLeft) || '0mm' %>;
|
||||
box-sizing: content-box;
|
||||
transform: scale(<%= scale || '1' %>);
|
||||
transform-origin: top left;
|
||||
}
|
||||
.renderDocument {
|
||||
width: <%= (width) || '50mm' %>;
|
||||
height: <%= (height) || '50mm' %>;
|
||||
padding: <%= (paddingTop) || '0mm' %> <%= (paddingRight) || '0mm' %> <%= (paddingBottom) || '0mm' %> <%= (paddingLeft) || '0mm' %>;
|
||||
box-sizing: content-box;
|
||||
width: <%= (scaledWidth) || '50mm' %>;
|
||||
height: <%= (scaledHeight) || '50mm' %>;
|
||||
transform: scale(<%= scale || '1' %>);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -25,11 +25,6 @@ body {
|
||||
transform-origin: top left;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.renderDocument {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.documentText {
|
||||
|
||||
@ -4,9 +4,7 @@ const { html: beautifyHtml, js: beautifyJs } = beautify;
|
||||
|
||||
const EJS_BLOCK_REGEX = /<%[\s\S]*?%>/g;
|
||||
const EJS_TAG_REGEX = /^<%([=#-]?)([\s\S]*?)%>/;
|
||||
const EJS_COMMENT_PLACEHOLDER_REGEX = /<!--EJS_PH_(\d+)-->/g;
|
||||
const EJS_INLINE_PLACEHOLDER_REGEX = /___EJS_PH_(\d+)___/g;
|
||||
const TEXT_ONLY_TAG_REGEX = /<([A-Za-z][\w:-]*)(\s[^>]*)?>([^<]*)<\/\1>/g;
|
||||
const EJS_PLACEHOLDER_REGEX = /<!--EJS_PH_(\d+)-->/g;
|
||||
|
||||
const HTML_BEAUTIFY_OPTIONS = {
|
||||
indent_size: 2,
|
||||
@ -49,53 +47,28 @@ function formatEjsTag(tag) {
|
||||
}
|
||||
}
|
||||
|
||||
function isControlEjs(tag) {
|
||||
const match = tag.match(EJS_TAG_REGEX);
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const [, modifier] = match;
|
||||
return !modifier;
|
||||
}
|
||||
|
||||
function maskEjsBlocks(content) {
|
||||
const ejsBlocks = [];
|
||||
|
||||
const masked = content.replace(EJS_BLOCK_REGEX, (match) => {
|
||||
const index = ejsBlocks.length;
|
||||
ejsBlocks.push(match);
|
||||
if (isControlEjs(match)) {
|
||||
return `\n<!--EJS_PH_${index}-->\n`;
|
||||
}
|
||||
return `___EJS_PH_${index}___`;
|
||||
return `\n<!--EJS_PH_${index}-->\n`;
|
||||
});
|
||||
|
||||
return { masked, ejsBlocks };
|
||||
}
|
||||
|
||||
function restoreEjsBlocks(content, ejsBlocks) {
|
||||
const restore = (_, index) => formatEjsTag(ejsBlocks[Number(index)]);
|
||||
return content
|
||||
.replace(EJS_COMMENT_PLACEHOLDER_REGEX, restore)
|
||||
.replace(EJS_INLINE_PLACEHOLDER_REGEX, restore);
|
||||
}
|
||||
|
||||
function collapseTextOnlyTags(content) {
|
||||
return content.replace(TEXT_ONLY_TAG_REGEX, (_, tagName, attrs, inner) => {
|
||||
const collapsedInner = inner.replace(/^\s+|\s+$/g, '');
|
||||
return `<${tagName}${attrs || ''}>${collapsedInner}</${tagName}>`;
|
||||
});
|
||||
return content.replace(EJS_PLACEHOLDER_REGEX, (_, index) =>
|
||||
formatEjsTag(ejsBlocks[Number(index)])
|
||||
);
|
||||
}
|
||||
|
||||
function tightenParenthesesAroundEjs(content) {
|
||||
return content.replace(/\(\s+(<%)/g, '($1').replace(/(%>)\s+\)/g, '$1)');
|
||||
}
|
||||
|
||||
function tightenColonsAroundEjs(content) {
|
||||
return content.replace(/:\s+(<%)/g, ':$1');
|
||||
}
|
||||
|
||||
export function formatTemplateContent(content) {
|
||||
if (content == null || typeof content !== 'string') {
|
||||
return { error: 'Content is required and must be a string.', code: 400 };
|
||||
@ -108,10 +81,8 @@ export function formatTemplateContent(content) {
|
||||
try {
|
||||
const { masked, ejsBlocks } = maskEjsBlocks(content);
|
||||
let formatted = beautifyHtml(masked, HTML_BEAUTIFY_OPTIONS);
|
||||
formatted = collapseTextOnlyTags(formatted);
|
||||
formatted = restoreEjsBlocks(formatted, ejsBlocks);
|
||||
formatted = tightenParenthesesAroundEjs(formatted);
|
||||
formatted = tightenColonsAroundEjs(formatted);
|
||||
return { content: formatted.trimEnd() };
|
||||
} catch (error) {
|
||||
return { error: error.message || 'Failed to format template content.', code: 400 };
|
||||
|
||||
@ -357,32 +357,6 @@ function imageToSvg(pngBuffer, widthPx, heightPx, documentWidthMm, documentHeigh
|
||||
</svg>`;
|
||||
}
|
||||
|
||||
function toPaddingMm(value) {
|
||||
const numeric = Number(value);
|
||||
return Number.isFinite(numeric) && numeric > 0 ? numeric : 0;
|
||||
}
|
||||
|
||||
export function resolveDocumentPadding(documentSize = {}, paddingRequested = false) {
|
||||
const applyPadding = documentSize.printPadding == true || paddingRequested == true;
|
||||
if (!applyPadding) {
|
||||
return {
|
||||
applyPadding: false,
|
||||
paddingLeft: 0,
|
||||
paddingRight: 0,
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
applyPadding: true,
|
||||
paddingLeft: toPaddingMm(documentSize.paddingLeft),
|
||||
paddingRight: toPaddingMm(documentSize.paddingRight),
|
||||
paddingTop: toPaddingMm(documentSize.paddingTop),
|
||||
paddingBottom: toPaddingMm(documentSize.paddingBottom),
|
||||
};
|
||||
}
|
||||
|
||||
export class TemplateManager {
|
||||
constructor() {
|
||||
this.fc = {
|
||||
@ -394,10 +368,9 @@ export class TemplateManager {
|
||||
|
||||
async renderTemplate(id, content, data = {}, scale = 1, options = {}, preview = true) {
|
||||
try {
|
||||
const { padding: paddingRequested = false, ...ejsOptions } = options;
|
||||
const defaultOptions = {
|
||||
async: true,
|
||||
...ejsOptions,
|
||||
...options,
|
||||
};
|
||||
logger.debug('Rendering template:', id);
|
||||
|
||||
@ -504,11 +477,6 @@ export class TemplateManager {
|
||||
}
|
||||
|
||||
const infiniteHeight = documentSize.infiniteHeight == true;
|
||||
const padding = resolveDocumentPadding(documentSize, paddingRequested == true);
|
||||
const pageWidth = (documentSize.width || 0) + padding.paddingLeft + padding.paddingRight;
|
||||
const pageHeight = infiniteHeight
|
||||
? null
|
||||
: (documentSize.height || 0) + padding.paddingTop + padding.paddingBottom;
|
||||
|
||||
const baseHtml = await ejs.render(
|
||||
baseTemplate,
|
||||
@ -518,12 +486,6 @@ export class TemplateManager {
|
||||
height: infiniteHeight ? 'fit-content' : `${documentSize.height}mm`,
|
||||
scaledWidth: `${documentSize.width * scale}mm`,
|
||||
scaledHeight: infiniteHeight ? 'auto' : `${documentSize.height * scale}mm`,
|
||||
scaledPageWidth: `${pageWidth * scale}mm`,
|
||||
scaledPageHeight: infiniteHeight ? 'auto' : `${pageHeight * scale}mm`,
|
||||
paddingTop: `${padding.paddingTop}mm`,
|
||||
paddingRight: `${padding.paddingRight}mm`,
|
||||
paddingBottom: `${padding.paddingBottom}mm`,
|
||||
paddingLeft: `${padding.paddingLeft}mm`,
|
||||
scale: `${scale}`,
|
||||
baseCSS: baseCSS,
|
||||
previewPaginationScript: preview ? previewPaginationScript : '',
|
||||
@ -533,14 +495,9 @@ export class TemplateManager {
|
||||
|
||||
return {
|
||||
html: baseHtml,
|
||||
width: pageWidth,
|
||||
height: infiniteHeight ? 'auto' : pageHeight,
|
||||
width: documentSize.width,
|
||||
height: infiniteHeight ? 'auto' : documentSize.height,
|
||||
infiniteHeight: infiniteHeight,
|
||||
printPadding: documentSize.printPadding == true,
|
||||
paddingLeft: padding.paddingLeft,
|
||||
paddingRight: padding.paddingRight,
|
||||
paddingTop: padding.paddingTop,
|
||||
paddingBottom: padding.paddingBottom,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@ -591,13 +548,12 @@ export class TemplateManager {
|
||||
try {
|
||||
logger.debug(`Rendering ${format} for template:`, id);
|
||||
|
||||
const { padding: _padding, ...imageOptions } = options;
|
||||
const pdfResult = await this.renderPDF(id, content, data, options);
|
||||
if (pdfResult.error != undefined) {
|
||||
return { error: pdfResult.error, code: pdfResult.code };
|
||||
}
|
||||
|
||||
const images = await convertPDFToImage(pdfResult.pdf, imageOptions);
|
||||
const images = await convertPDFToImage(pdfResult.pdf, options);
|
||||
const converted = [];
|
||||
for (const image of images) {
|
||||
if (format === 'png') {
|
||||
@ -617,13 +573,12 @@ export class TemplateManager {
|
||||
try {
|
||||
logger.debug('Rendering SVG for template:', id);
|
||||
|
||||
const { padding: _padding, ...imageOptions } = options;
|
||||
const pdfResult = await this.renderPDF(id, content, data, options);
|
||||
if (pdfResult.error != undefined) {
|
||||
return { error: pdfResult.error, code: pdfResult.code };
|
||||
}
|
||||
|
||||
const images = await convertPDFToImage(pdfResult.pdf, imageOptions);
|
||||
const images = await convertPDFToImage(pdfResult.pdf, options);
|
||||
const svgs = [];
|
||||
for (const image of images) {
|
||||
const png = await sharp(image).png().toBuffer();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user