UNPKG

survey-pdf

Version:

Renders JSON-driven SurveyJS forms and their responses as PDF documents in the browser or Node.js: fillable interactive PDF forms (AcroForm) or static printouts.

156 lines (151 loc) 7.24 kB
/*! * surveyjs - SurveyJS PDF library v3.0.2 * Copyright (c) 2015-2026 Devsoft Baltic OÜ - http://surveyjs.io/ * License: MIT (http://www.opensource.org/licenses/mit-license.php) */ import { B as BaseImageUtils, r as rgbaToHex, a as registerImageUtils, b as registerVariablesManagerCreator } from './pdf-shared.mjs'; export { C as CheckItemBrick, c as CompositeBrick, d as CustomBrick, D as DocController, e as DocOptions, f as DrawCanvas, g as DropdownBrick, E as EmptyBrick, h as EventHandler, F as FlatBoolean, i as FlatCheckbox, j as FlatComment, k as FlatCustomModel, l as FlatDropdown, m as FlatExpression, n as FlatFile, o as FlatHTML, p as FlatImage, q as FlatImagePicker, s as FlatMatrix, t as FlatMatrixDynamic, u as FlatMatrixMultiple, v as FlatMultipleText, w as FlatPage, x as FlatPanel, y as FlatPanelDynamic, z as FlatQuestion, A as FlatQuestionDefault, G as FlatRadiogroup, H as FlatRanking, I as FlatRating, J as FlatRepository, K as FlatSelectBase, L as FlatSignaturePad, M as FlatSlider, N as FlatSurvey, O as FlatTextbox, P as HTMLBrick, Q as HorizontalAlign, R as ImageBrick, S as LinkBrick, T as PagePacker, U as PdfBrick, V as RadioItemBrick, W as RankingItemBrick, X as RowlineBrick, Y as SurveyHelper, Z as SurveyPDF, _ as TextBrick, $ as TextFieldBrick, a0 as VerticalAlign } from './pdf-shared.mjs'; import fetch from 'node-fetch'; import { imageSize } from 'image-size'; import { calcFromComponentValues } from '@csstools/css-calc'; import { color, serializeRGB } from '@csstools/css-color-parser'; import { parseListOfComponentValues, parseComponentValue, FunctionNode } from '@csstools/css-parser-algorithms'; import { tokenizer, stringify, tokenize } from '@csstools/css-tokenizer'; import 'survey-core'; import 'jspdf'; class ImageUtils extends BaseImageUtils { async _getImageInfo(url) { const pxToPt = 72.0 / 96.0; let data; if (typeof url === 'string' && url.startsWith('data:')) { data = Buffer.from(url.split(',')[1] || '', 'base64'); } else { const res = await fetch(url); data = new Uint8Array(await res.arrayBuffer()); } const size = imageSize(data); return { data: data, width: size.width * pxToPt, height: size.height * pxToPt, id: this.getImageId() }; } } class VariablesManager { setup(variables) { this.hash = {}; this.colorHash = {}; this.variables = variables; } tokenizeString(css) { const t = tokenizer({ css }); const tokens = []; while (!t.endOfFile()) { tokens.push(t.nextToken()); } tokens.push(t.nextToken()); return tokens; } splitComponentValuesByTopLevelComma(tokens) { const parts = []; let curr = []; for (const tok of tokens) { if (tok.type == 'token' && tok.value[0] == 'comma-token') { parts.push(curr); curr = []; } else { curr.push(tok); } } parts.push(curr); return parts; } getVariable(name) { if (!name) return name; if (!this.variables || !this.hash) return undefined; if (!this.variables[name]) return undefined; if (this.hash[name]) return this.hash[name]; let value = this.variables[name]; const componentValues = parseListOfComponentValues(this.tokenizeString(value)); const replaceVars = (componentValues, depth = 0) => { if (depth > 50) return componentValues; const out = []; for (const componentValue of componentValues) { if (componentValue.type === 'function') { const functionComponentValue = componentValue; const lowerName = (functionComponentValue.getName()).toLowerCase(); if (lowerName === 'var') { const inner = functionComponentValue.value || []; const parts = this.splitComponentValuesByTopLevelComma(inner); const nameTokens = parts[0] || []; const fallbackTokens = parts.length > 1 ? parts[1] : null; const variableName = nameTokens.map((x) => stringify(...x.tokens())).join('').trim(); let replacementTokens = []; const variableValue = this.getVariable(variableName); if (!!variableValue) { const componentValue = parseListOfComponentValues(this.tokenizeString(variableValue)); replacementTokens = componentValue; } else if (fallbackTokens && fallbackTokens.length > 0) { replacementTokens = replaceVars(fallbackTokens, depth + 1); } else { replacementTokens = []; } out.push(...replacementTokens); continue; } else { const inner = functionComponentValue.value || []; const resolvedInner = replaceVars(inner, depth + 1); out.push(new FunctionNode(functionComponentValue.name, functionComponentValue.endToken, resolvedInner)); continue; } } else { out.push(componentValue); } } return out; }; const replacedComponentValues = replaceVars(componentValues); const processedValue = calcFromComponentValues([replacedComponentValues]).map(componentValues => componentValues.map((componentValue) => stringify(...componentValue.tokens())).join('')).join(','); this.hash[name] = processedValue; return processedValue; } getSizeVariable(name) { const valueString = this.getVariable(name); if (!valueString) { return 0; } if (valueString.match(/px$/)) { return Number.parseFloat(valueString) * 72.0 / 96.0; } else { return Number.parseFloat(valueString); } } getColorVariable(name) { const valueString = this.getVariable(name); if (!this.colorHash[valueString]) { const hwbComponentValue = parseComponentValue(tokenize({ css: valueString })); const colorData = color(hwbComponentValue); if (colorData) { const rgbComponentValue = serializeRGB(colorData); this.colorHash[valueString] = rgbaToHex(rgbComponentValue.toString()); } else { this.colorHash[valueString] = '#000000'; } } return this.colorHash[valueString]; } startCollectingVariables() { } stopCollectingVariables() { } } registerImageUtils(new ImageUtils()); registerVariablesManagerCreator(() => new VariablesManager()); //# sourceMappingURL=survey.pdf.node.mjs.map