Skip to content

fix/arearange-tracker #651

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ OTHER_LISTEN_TO_PROCESS_EXITS = true
OTHER_NO_LOGO = false
OTHER_HARD_RESET_PAGE = false
OTHER_BROWSER_SHELL_MODE = true
OTHER_EXCLUDE_CLASSES = highcharts-tracker-area

# DEBUG CONFIG
DEBUG_ENABLE = false
Expand Down
9 changes: 9 additions & 0 deletions lib/envs.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,15 @@ export const Config = z.object({
OTHER_HARD_RESET_PAGE: v.boolean(),
OTHER_BROWSER_SHELL_MODE: v.boolean(),
OTHER_ALLOW_XLINK: v.boolean(),
OTHER_EXCLUDE_CLASSES: z
.string()
.transform((value) =>
value
.split(',')
.map((value) => value.trim())
.filter((value) => value !== '')
)
.transform((value) => (value.length ? value : undefined)),

// debugger
DEBUG_ENABLE: v.boolean(),
Expand Down
3 changes: 2 additions & 1 deletion lib/export.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { addPageResources, clearPageResources } from './browser.js';
import { getCache } from './cache.js';
import { triggerExport } from './highcharts.js';
import { log } from './logger.js';
import { sanitizeSVG } from './sanitize.js';

import svgTemplate from './../templates/svg_export/svg_export.js';

Expand Down Expand Up @@ -292,7 +293,7 @@ export default async (page, chart, options) => {
// Rasterization process
if (exportOptions.type === 'svg') {
// SVG
data = await createSVG(page);
data = sanitizeSVG(await createSVG(page));
} else if (['png', 'jpeg'].includes(exportOptions.type)) {
// PNG or JPEG
data = await createImage(
Expand Down
54 changes: 54 additions & 0 deletions lib/sanitize.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,65 @@ import { JSDOM } from 'jsdom';
import DOMPurify from 'dompurify';

import { envs } from './envs.js';

// List of class names to be excluded from sanitization of SVG
const excludedClasses = envs.OTHER_EXCLUDE_CLASSES || [];

/**
* Registers a DOMPurify hook to remove elements with specific class names
* during sanitization.
*
* @param {Window} window - The window object, used to access DOM constructors
* like `Element`.
* @param {DOMPurify.DOMPurifyI} purify - The DOMPurify instance to which the
* hook will be added.
*/
export function excludeElementsByClass(window, purify) {
// Add a hook to remove elements during sanitization
purify.addHook('uponSanitizeElement', (node) => {
excludedClasses.forEach((className) => {
// Check if the element has the excluded class
if (
node instanceof window.Element &&
node.getAttribute('class')?.includes(className)
) {
// Remove the node from the DOM
node.parentNode?.removeChild(node);
}
});
});
}

/**
* Sanitizes a given SVG string by removing potential element of specified class
* names.
*
* @param {string} input The SVG string to be sanitized.
* @param {Object} [options={}] Optional configuration options for DOMPurify.
*
* @returns {string} The sanitized SVG string.
*/
export function sanitizeSVG(input, options = {}) {
// Check if sanitization is needed
if (excludedClasses.length) {
const window = new JSDOM('').window;
const purify = DOMPurify(window);

excludeElementsByClass(window, purify);
return purify.sanitize(input, {
RETURN_DOM: false,
...options
});
}
}

/**
* Sanitizes a given HTML string by removing <script> tags.
* This function uses a regular expression to find and remove all
* occurrences of <script>...</script> tags and any content within them.
*
* @param {string} input The HTML string to be sanitized.
*
* @returns {string} The sanitized HTML string.
*/
export function sanitize(input) {
Expand All @@ -38,6 +91,7 @@ export function sanitize(input) {

const window = new JSDOM('').window;
const purify = DOMPurify(window);

return purify.sanitize(input, {
ADD_TAGS: ['foreignObject'],
FORBID_ATTR: forbidden
Expand Down
Loading