diff --git a/x-pack/platform/plugins/shared/screenshotting/server/browsers/chromium/templates/index.test.ts b/x-pack/platform/plugins/shared/screenshotting/server/browsers/chromium/templates/index.test.ts
new file mode 100644
index 0000000000000..90fdf4576c59e
--- /dev/null
+++ b/x-pack/platform/plugins/shared/screenshotting/server/browsers/chromium/templates/index.test.ts
@@ -0,0 +1,124 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { getHeaderTemplate, getFooterTemplate, getDefaultFooterLogo } from '.';
+
+let defaultFooterLogo: string;
+
+describe('templates/index', () => {
+ beforeAll(async () => {
+ defaultFooterLogo = (await getDefaultFooterLogo()).trim();
+ });
+
+ describe('getHeaderTemplate()', () => {
+ it('works with a plain logo', async () => {
+ const title = 'plain';
+ const result = await getHeaderTemplate({ title });
+ expect(result).toBe(getHeader(title));
+ });
+ it('works with an html title', async () => {
+ const title = 'html';
+ const result = await getHeaderTemplate({ title });
+ expect(result).toBe(getHeader('<b>html</b>'));
+ });
+ });
+
+ describe('getFooterTemplate()', () => {
+ it('works with no logo', async () => {
+ const result = await getFooterTemplate({});
+ expect(result).toBe(getFooter());
+ });
+ it('works with a plain logo', async () => {
+ const logo = 'http://example.com/favico.ico';
+ const result = await getFooterTemplate({ logo });
+ expect(result).toBe(getFooter(logo));
+ });
+ it('works with an html logo', async () => {
+ const logo = '"/>
${title}
+`.trimStart();
+}
+
+function getFooter(logo?: string): string {
+ const hasLogo = !!logo;
+
+ if (!hasLogo) {
+ logo = defFooterLogo();
+ }
+ return `
+
+
+
+

+${getPoweredBy(hasLogo)}
+ of
+
+
+`.trimStart();
+}
+
+function getPoweredBy(hasLogo: boolean): string {
+ if (!hasLogo) return '';
+ return ` Powered by Elastic
\n`;
+}
+
+function defFooterLogo(): string {
+ return defaultFooterLogo!;
+}
diff --git a/x-pack/platform/plugins/shared/screenshotting/server/browsers/chromium/templates/index.ts b/x-pack/platform/plugins/shared/screenshotting/server/browsers/chromium/templates/index.ts
index 7034dac76cfca..179e21ce94265 100644
--- a/x-pack/platform/plugins/shared/screenshotting/server/browsers/chromium/templates/index.ts
+++ b/x-pack/platform/plugins/shared/screenshotting/server/browsers/chromium/templates/index.ts
@@ -8,12 +8,27 @@
import { i18n } from '@kbn/i18n';
import fs from 'fs/promises';
import path from 'path';
-import Handlebars from 'handlebars';
+import Handlebars, { TemplateDelegate } from '@kbn/handlebars';
import { assetPath } from '../../../constants';
-async function compileTemplate(pathToTemplate: string): Promise> {
+// see: https://handlebarsjs.com/guide/builtin-helpers.html
+const HBCompileOptions = {
+ knownHelpersOnly: true,
+ knownHelpers: {
+ helperMissing: false,
+ blockHelperMissing: false,
+ each: false,
+ if: true,
+ unless: false,
+ with: false,
+ log: false,
+ lookup: false,
+ },
+};
+
+async function compileTemplate(pathToTemplate: string): Promise> {
const contentsBuffer = await fs.readFile(pathToTemplate);
- return Handlebars.compile(contentsBuffer.toString());
+ return Handlebars.compileAST(contentsBuffer.toString(), HBCompileOptions);
}
interface HeaderTemplateInput {
@@ -30,7 +45,7 @@ export async function getHeaderTemplate({ title }: GetHeaderArgs): Promise {
+export async function getDefaultFooterLogo(): Promise {
const logoBuffer = await fs.readFile(path.resolve(assetPath, 'img', 'logo-grey.png'));
return `data:image/png;base64,${logoBuffer.toString('base64')}`;
}
diff --git a/x-pack/platform/plugins/shared/screenshotting/tsconfig.json b/x-pack/platform/plugins/shared/screenshotting/tsconfig.json
index 200c6d9c2592e..67363ecf6ffde 100644
--- a/x-pack/platform/plugins/shared/screenshotting/tsconfig.json
+++ b/x-pack/platform/plugins/shared/screenshotting/tsconfig.json
@@ -26,6 +26,7 @@
"@kbn/core-plugins-server",
"@kbn/task-manager-plugin",
"@kbn/screenshotting-server",
+ "@kbn/handlebars",
],
"exclude": [
"target/**/*",