{
    "sourceFile": "plugins/print/rendering-info.js",
    "activeCommit": 0,
    "commits": [
        {
            "activePatchIndex": 0,
            "patches": [
                {
                    "date": 1698924615452,
                    "content": "Index: \n===================================================================\n--- \n+++ \n"
                }
            ],
            "date": 1698924615452,
            "name": "Commit-0",
            "content": "const Joi = require(\"../../helper/custom-joi.js\");\nconst Boom = require(\"@hapi/boom\");\nconst querystring = require(\"querystring\");\nconst fs = require(\"fs\").promises;\nconst util = require(\"util\");\nconst exec = util.promisify(require(\"child_process\").exec);\nconst crypto = require(\"crypto\");\nconst getInnerWidth = require(\"../screenshot/helpers.js\").getInnerWidth;\n\nconst {\n  getCmykTiffBufferFromPng,\n  promoteTiffBufferToBlack,\n} = require(\"./conversions.js\");\nconst { getPDF } = require(\"../screenshot/helpers.js\");\n\n// this seems to be the standard chrome points per pixel unit\nconst chromePPI = 96;\n\nfunction mmToInch(mm) {\n  return mm / 25.4;\n}\n\nmodule.exports = {\n  method: \"POST\",\n  path: \"/print/rendering-info.{format}\",\n  options: {\n    validate: {\n      options: {\n        allowUnknown: true,\n      },\n      params: {\n        format: Joi.string().valid(\"png\", \"pdf\", \"tiff\", \"tif\"),\n      },\n      payload: {\n        item: Joi.object().required(),\n        toolRuntimeConfig: Joi.object()\n          .required()\n          .keys({\n            displayOptions: Joi.object().required().keys({\n              columns: Joi.number().required(),\n            }),\n          }),\n      },\n      query: {\n        _id: Joi.string().required(),\n      },\n    },\n    cache: {\n      expiresIn: 1000 * 60, // 60 seconds\n    },\n    tags: [\"api\"],\n  },\n  handler: async function (request, h) {\n    try {\n      const displayOptions = request.payload.toolRuntimeConfig.displayOptions;\n      const screenshotRequestQuery = {};\n\n      if (displayOptions && displayOptions.printTitle) {\n        request.payload.item.title = displayOptions.printTitle;\n      }\n\n      if (displayOptions && displayOptions.printSubtitle) {\n        request.payload.item.subtitle = displayOptions.printSubtitle;\n      }\n\n      if (displayOptions && displayOptions.printNotes) {\n        request.payload.item.notes = displayOptions.printNotes;\n      }\n\n      screenshotRequestToolRuntimeConfig = JSON.parse(\n        JSON.stringify(request.payload.toolRuntimeConfig)\n      );\n\n      // pass all the displayOptions to the tool\n      // set hideTitle to true if the titleStyle is 'hide'\n      screenshotRequestToolRuntimeConfig.displayOptions = Object.assign(\n        displayOptions,\n        {\n          hideTitle: displayOptions.titleStyle === \"hide\",\n        }\n      );\n\n      const screenshotRequestPayload = {\n        toolRuntimeConfig: screenshotRequestToolRuntimeConfig,\n        item: request.payload.item,\n      };\n\n      const dpi = request.payload.toolRuntimeConfig.dpi || 300;\n      screenshotRequestQuery.dpr = dpi / chromePPI;\n\n      // the screenshot width is the width in inch * target dpi\n      const mm = await request.server.methods.plugins.q.print.colsToMm(\n        displayOptions.columnsProfile,\n        displayOptions.columns\n      );\n\n      screenshotRequestQuery.width = Math.round(\n        (mmToInch(mm) * dpi) / screenshotRequestQuery.dpr\n      );\n      screenshotRequestQuery.background =\n        screenshotRequestQuery.background || \"white\";\n      screenshotRequestQuery.wait =\n        request.payload.toolRuntimeConfig.wait || 2000;\n      screenshotRequestQuery.target = await request.server.settings.app.print\n        .target;\n\n      const screenshotImageResponse = await request.server.inject({\n        method: \"POST\",\n        url: `/screenshot.png?${querystring.stringify(screenshotRequestQuery)}`,\n        payload: screenshotRequestPayload,\n      });\n\n      // fail early if there is an error to generate the screenshot\n      if (screenshotImageResponse.statusCode !== 200) {\n        request.server.log([\"error\"], screenshotImageResponse.payload);\n        return screenshotImageResponse;\n      }\n\n      if (request.params.format === \"png\") {\n        return h.response(screenshotImageResponse.rawPayload).type(\"image/png\");\n      }\n\n      return await new Promise(async (resolve, reject) => {\n        // TODO:\n        const server =request.server;\n        const target = server.settings.app.targets.get(`/${screenshotRequestQuery.target}`);\n\n\n        const width = getInnerWidth(screenshotRequestQuery.width, screenshotRequestQuery.padding);\n        if (width) {\n          request.payload.toolRuntimeConfig.size = {\n            width: [\n              {\n                value: width,\n                unit: \"px\",\n                comparison: \"=\",\n              },\n            ],\n          };\n        }\n\n\n        const response = await server.inject({\n          method: \"POST\",\n          url: `/rendering-info/${screenshotRequestQuery.target}`,\n          payload: {\n            toolRuntimeConfig: request.payload.toolRuntimeConfig,\n            item: request.payload.item,\n            ignoreInactive: true,\n          },\n        });\n\n        const renderingInfo = JSON.parse(response.payload);\n\n        let scripts = await server.methods.plugins.q.screenshot.getScripts(\n          renderingInfo\n        );\n        let stylesheets = await server.methods.plugins.q.screenshot.getStylesheets(\n          renderingInfo\n        );\n\n        if (Array.isArray(target.context.scripts)) {\n          scripts = target.scripts.context.concat(scripts);\n        }\n        if (Array.isArray(target.context.stylesheets)) {\n          stylesheets = target.context.stylesheets.concat(stylesheets);\n        }\n\n        const config = {\n          width: screenshotRequestQuery.width,\n          dpr: screenshotRequestQuery.dpr || 1,\n          padding: screenshotRequestQuery.padding || \"0\",\n          background: screenshotRequestQuery.background,\n        };\n\n        const pdf = await getPDF(\n          `${server.info.protocol}://localhost:${server.info.port}/screenshot/empty-page.html`,\n          renderingInfo.markup,\n          scripts,\n          stylesheets,\n          config\n        )\n\n        // const pngBuffer = screenshotImageResponse.rawPayload;\n        // const profiles = await request.server.settings.app.print.profiles;\n        // const tiffBuffer = await getCmykTiffBufferFromPng(\n        //   pngBuffer,\n        //   dpi,\n        //   profiles\n        // );\n        // const finalTiffBuffer = await promoteTiffBufferToBlack(tiffBuffer);\n\n        // if a TIFF is requested we return it here\n        if (\n          request.params.format === \"tiff\" ||\n          request.params.format === \"tif\"\n        ) {\n          return resolve(finalTiffBuffer);\n        }\n\n        // if the format is not pdf here, we have a problem and return this\n        if (request.params.format !== \"pdf\") {\n          throw Boom.badRequest();\n        }\n\n        // const requestId = crypto\n        //   .createHash(\"sha1\")\n        //   .update(request.info.id)\n        //   .digest(\"hex\");\n\n        // the following could all be optimised maybe by implementing it using streams and buffers\n        // instead of writing and reading files\n        // but we do it easy for now...\n        // const fileNameBase = `${__dirname}/${requestId}`;\n\n        // write the tiff buffer to disk\n        // await fs.writeFile(`${fileNameBase}orig.tiff`, tiffBuffer);\n        // remove the alpha channel for tiff2pdf to work\n        // const { stdoutA, stderrA } = await exec(\n        //   `convert ${fileNameBase}orig.tiff -alpha off -compress lzw ${fileNameBase}-no-alpha.tiff`\n        // );\n\n        // we need to use tiff2pdf instead of imagemagick since this produces pdf v1.3 compatible PDFs where imagemagick does not\n        // const { stdoutP, stderrP } = await exec(\n        //   `tiff2pdf -z -o ${fileNameBase}.pdf ${fileNameBase}-no-alpha.tiff`\n        // );\n\n        // const pdfBuffer = await fs.readFile(`${fileNameBase}.pdf`);\n\n        resolve(h.response(pdf).type(\"application/pdf\"));\n\n        // remove all the intermediate files\n        // fs.unlink(`${fileNameBase}orig.tiff`);\n        // fs.unlink(`${fileNameBase}-no-alpha.tiff`);\n        // fs.unlink(`${fileNameBase}.pdf`);\n      });\n    } catch (e) {\n      request.server.log([\"error\"], e);\n      throw e;\n    }\n  },\n};\n"
        }
    ]
}