From e01b6ee95b863dbebf74b19406c758161860f751 Mon Sep 17 00:00:00 2001 From: Dmitry Kuzin Date: Mon, 27 Nov 2023 06:50:17 +0400 Subject: [PATCH 1/5] Fix signature pad is failing with empty value on Node --- src/flat_layout/flat_signaturepad.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/flat_layout/flat_signaturepad.ts b/src/flat_layout/flat_signaturepad.ts index b4aef874..36153f99 100644 --- a/src/flat_layout/flat_signaturepad.ts +++ b/src/flat_layout/flat_signaturepad.ts @@ -5,6 +5,7 @@ import { FlatRepository } from './flat_repository'; import { IPoint, DocController } from '../doc_controller'; import { IPdfBrick } from '../pdf_render/pdf_brick'; import { SurveyHelper } from '../helper_survey'; +import { EmptyBrick } from '../pdf_render/pdf_empty'; export class FlatSignaturePad extends FlatQuestion { protected question: QuestionSignaturePadModel; @@ -14,11 +15,19 @@ export class FlatSignaturePad extends FlatQuestion { this.question = question; } public async generateFlatsContent(point: IPoint): Promise { - let imageBrick = await SurveyHelper.createImageFlat(point, - this.question, this.controller, this.question.value, - SurveyHelper.pxToPt(this.question.signatureWidth), - SurveyHelper.pxToPt(this.question.signatureHeight) - ); + const width = SurveyHelper.pxToPt(this.question.signatureWidth); + const height = SurveyHelper.pxToPt(this.question.signatureHeight); + let imageBrick: IPdfBrick; + if(this.question.value) { + imageBrick = await SurveyHelper.createImageFlat(point, + this.question, this.controller, this.question.value, + width, + height + ); + } else { + imageBrick = new EmptyBrick(SurveyHelper.createRect(point, width, height)); + + } return [imageBrick]; } } From 726eae89f7b72291a0f096435129b6e5a73b8b9e Mon Sep 17 00:00:00 2001 From: Dmitry Kuzin Date: Mon, 27 Nov 2023 07:08:24 +0400 Subject: [PATCH 2/5] Render Empty brick insteadof html brick when document is not defined --- src/flat_layout/flat_html.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/flat_layout/flat_html.ts b/src/flat_layout/flat_html.ts index cc8a7f74..357171de 100644 --- a/src/flat_layout/flat_html.ts +++ b/src/flat_layout/flat_html.ts @@ -5,6 +5,7 @@ import { FlatQuestion } from './flat_question'; import { FlatRepository } from './flat_repository'; import { IPdfBrick } from '../pdf_render/pdf_brick'; import { SurveyHelper } from '../helper_survey'; +import { EmptyBrick } from '../pdf_render/pdf_empty'; export type IHTMLRenderType = 'auto' | 'standard' | 'image'; export class FlatHTML extends FlatQuestion { @@ -23,6 +24,9 @@ export class FlatHTML extends FlatQuestion { } public async generateFlatsContent(point: IPoint): Promise { let renderAs: IHTMLRenderType = this.question.renderAs; + if(!SurveyHelper.inBrowser) { + return [new EmptyBrick(SurveyHelper.createRect(point, 0, 0))]; + } if (renderAs === 'auto') renderAs = this.controller.htmlRenderAs; if (renderAs === 'auto') renderAs = this.chooseRender(SurveyHelper.getLocString(this.question.locHtml)); const html: string = SurveyHelper.createHtmlContainerBlock(SurveyHelper.getLocString(this.question.locHtml), this.controller, renderAs); From 0bef2f8f2013d081bb60d87fef51d5586801e539 Mon Sep 17 00:00:00 2001 From: Dmitry Kuzin Date: Mon, 27 Nov 2023 17:12:57 +0400 Subject: [PATCH 3/5] Fix image rendering fails on Node --- src/helper_survey.ts | 1 - src/pdf_render/pdf_image.ts | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/helper_survey.ts b/src/helper_survey.ts index 8303c024..9e3b0a50 100644 --- a/src/helper_survey.ts +++ b/src/helper_survey.ts @@ -497,7 +497,6 @@ export class SurveyHelper { const html: string = ``; return new HTMLBrick(question, controller, this.createRect(point, width, height), html, true); } - return new ImageBrick(question, controller, imagelink, point, width, height); } public static canPreviewImage(question: QuestionFileModel, item: { name: string, type: string, content: string }, url: string): boolean { diff --git a/src/pdf_render/pdf_image.ts b/src/pdf_render/pdf_image.ts index d3a2f96e..8b499657 100644 --- a/src/pdf_render/pdf_image.ts +++ b/src/pdf_render/pdf_image.ts @@ -16,7 +16,12 @@ export class ImageBrick extends PdfBrick { } public async renderInteractive(): Promise { await new Promise((resolve) => { - this.controller.doc.addImage(this.image, this.xLeft, this.yTop, this.originalWidth, this.originalHeight); + try { + this.controller.doc.addImage(this.image, 'PNG', this.xLeft, this.yTop, this.originalWidth, this.originalHeight); + } catch { + // eslint-disable-next-line no-console + console.warn('It is impossible to render an image whose url is not base64 in a non-browser environment'); + } resolve(); }); } From 61a351d187ae8ba24425c2381346bf1d8f1fe790 Mon Sep 17 00:00:00 2001 From: Dmitry Kuzin Date: Wed, 21 Feb 2024 15:34:56 +0400 Subject: [PATCH 4/5] Small refactor --- src/flat_layout/flat_signaturepad.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flat_layout/flat_signaturepad.ts b/src/flat_layout/flat_signaturepad.ts index f86d4133..83631a75 100644 --- a/src/flat_layout/flat_signaturepad.ts +++ b/src/flat_layout/flat_signaturepad.ts @@ -25,8 +25,8 @@ export class FlatSignaturePad extends FlatQuestion { if(this.question.value) { return await SurveyHelper.createImageFlat(point, this.question, this.controller, { link: this.question.value, - width: SurveyHelper.pxToPt(this.question.signatureWidth), - height: SurveyHelper.pxToPt(this.question.signatureHeight) }, false + width: width, + height: height }, false ); } else { return new EmptyBrick(SurveyHelper.createRect(point, width, height)); From 1f1e97d93aab5a14add5d2a8bbf87e43671c55f1 Mon Sep 17 00:00:00 2001 From: Dmitry Kuzin Date: Mon, 26 Feb 2024 15:42:36 +0400 Subject: [PATCH 5/5] Refactor + unit tests --- src/flat_layout/flat_html.ts | 2 +- src/helper_survey.ts | 4 ++ src/pdf_render/pdf_image.ts | 6 +-- tests/node.tests.ts | 83 ++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 tests/node.tests.ts diff --git a/src/flat_layout/flat_html.ts b/src/flat_layout/flat_html.ts index c313230e..fa20bcc8 100644 --- a/src/flat_layout/flat_html.ts +++ b/src/flat_layout/flat_html.ts @@ -24,7 +24,7 @@ export class FlatHTML extends FlatQuestion { } public async generateFlatsContent(point: IPoint): Promise { let renderAs: IHTMLRenderType = this.question.renderAs; - if(!SurveyHelper.inBrowser) { + if(!SurveyHelper.hasDocument) { return [new EmptyBrick(SurveyHelper.createRect(point, 0, 0))]; } if (renderAs === 'auto') renderAs = this.controller.htmlRenderAs; diff --git a/src/helper_survey.ts b/src/helper_survey.ts index 604961e9..517ce0a7 100644 --- a/src/helper_survey.ts +++ b/src/helper_survey.ts @@ -451,6 +451,10 @@ export class SurveyHelper { } public static inBrowser = typeof Image === 'function'; + public static get hasDocument(): boolean { + return typeof document !== 'undefined'; + } + public static async getImageBase64(imageLink: string): Promise { const image = new Image(); image.crossOrigin='anonymous'; diff --git a/src/pdf_render/pdf_image.ts b/src/pdf_render/pdf_image.ts index 8b499657..e876eadd 100644 --- a/src/pdf_render/pdf_image.ts +++ b/src/pdf_render/pdf_image.ts @@ -18,11 +18,9 @@ export class ImageBrick extends PdfBrick { await new Promise((resolve) => { try { this.controller.doc.addImage(this.image, 'PNG', this.xLeft, this.yTop, this.originalWidth, this.originalHeight); - } catch { - // eslint-disable-next-line no-console - console.warn('It is impossible to render an image whose url is not base64 in a non-browser environment'); + } finally { + resolve(); } - resolve(); }); } } \ No newline at end of file diff --git a/tests/node.tests.ts b/tests/node.tests.ts new file mode 100644 index 00000000..98bf3da2 --- /dev/null +++ b/tests/node.tests.ts @@ -0,0 +1,83 @@ + +/** + * @jest-environment node + */ +import { SurveyPDF } from '../src/survey'; +import { DocController, IRect } from '../src/doc_controller'; +import { FlatSurvey } from '../src/flat_layout/flat_survey'; +import { IPdfBrick } from '../src/pdf_render/pdf_brick'; +import { TestHelper } from '../src/helper_test'; +import { EmptyBrick } from '../src/pdf_render/pdf_empty'; +import { SurveyHelper } from '../src/helper_survey'; +import { CompositeBrick } from '../src/pdf_render/pdf_composite'; +import { ImageBrick } from '../src/pdf_render/pdf_image'; + +test('Check html brick is empty when document is not defined', async () => { + let json: any = { + elements: [ + { + type: 'html', + name: 'html_chooserender_standard', + html: 'STRONG POWER' + }, + ] + }; + let survey: SurveyPDF = new SurveyPDF(json, TestHelper.defaultOptions); + let controller: DocController = new DocController(TestHelper.defaultOptions); + let flats: IPdfBrick[][] = await FlatSurvey.generateFlats(survey, controller); + expect(flats.length).toBe(1); + expect(flats[0].length).toBe(1); + const emptyBrick = flats[0][0].unfold()[0]; + expect(emptyBrick instanceof EmptyBrick).toBe(true); + expect(emptyBrick.height).toEqual(0); + expect(emptyBrick.width).toEqual(0); +}); + +test('Check signaturepad with empty value', async () => { + let json: any = { + questions: [ + { + type: 'signaturepad', + name: 'sigpadque', + titleLocation: 'hidden', + } + ] + }; + let survey: SurveyPDF = new SurveyPDF(json, TestHelper.defaultOptions); + let controller: DocController = new DocController(TestHelper.defaultOptions); + let flats: IPdfBrick[][] = await FlatSurvey.generateFlats(survey, controller); + expect(flats.length).toBe(1); + expect(flats[0].length).toBe(1); + expect(flats[0][0] instanceof CompositeBrick).toBeTruthy(); + expect((flats[0][0])['bricks'].length).toBe(1); + const htmlBrick = (flats[0][0])['bricks'][0]; + expect(htmlBrick instanceof EmptyBrick).toBeTruthy(); + let assumeHTML: IRect = { + xLeft: controller.leftTopPoint.xLeft + controller.unitWidth, + xRight: controller.leftTopPoint.xLeft + controller.unitWidth + + SurveyHelper.pxToPt((survey.getAllQuestions()[0]).signatureWidth), + yTop: controller.leftTopPoint.yTop, + yBot: controller.leftTopPoint.yTop + + SurveyHelper.pxToPt((survey.getAllQuestions()[0]).signatureHeight) + }; + TestHelper.equalRect(expect, htmlBrick, assumeHTML); +}); + +test('Check image with non base64 link', async () => { + const json: any = { + elements: [ + { + type: 'image', + name: 'image_question', + titleLocation: 'hidden', + imageLink: 'https://surveyjs.io/Content/Images/examples/image-picker/lion.jpg' + } + ] + }; + const survey: SurveyPDF = new SurveyPDF(json, TestHelper.defaultOptions); + try { + await survey.raw(); + } catch { + throw(new Error('Could not export pdf')); + } +}); \ No newline at end of file