From b8ecc246fcf8ace24dc7adbc46ebea2f8ebc55c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gu=CC=88nther?= Date: Mon, 2 Dec 2024 21:33:05 +0100 Subject: [PATCH] BUGFIX: Render table dropdowns with correct icons The icons were broken and the fallback title was not aligned pretty well. So the SVG markup string will be transformed now to an data-uri and this can be used as image sorce. --- .../src/EditorToolbar/TableDropDown.js | 5 +- packages/utils-helpers/src/index.ts | 2 + packages/utils-helpers/src/svgToDataUri.ts | 47 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 packages/utils-helpers/src/svgToDataUri.ts diff --git a/packages/neos-ui-ckeditor5-bindings/src/EditorToolbar/TableDropDown.js b/packages/neos-ui-ckeditor5-bindings/src/EditorToolbar/TableDropDown.js index 85a1ae29c5..547123a947 100644 --- a/packages/neos-ui-ckeditor5-bindings/src/EditorToolbar/TableDropDown.js +++ b/packages/neos-ui-ckeditor5-bindings/src/EditorToolbar/TableDropDown.js @@ -3,6 +3,7 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import {neos} from '@neos-project/neos-ui-decorators'; +import {svgToDataUri} from '@neos-project/utils-helpers'; import ckeIcons from './icons'; import style from './TableDropDown.module.css'; @@ -39,12 +40,14 @@ export default class TableDropDownButton extends PureComponent { } render() { + const iconDataUri = svgToDataUri(ckeIcons[this.props.icon]); + console.log({iconDataUri}); return ( - {this.props.i18nRegistry.translate(this.props.tooltip)} + {this.props.i18nRegistry.translate(this.props.tooltip)} {this.props.options.map(item => item.type === 'checkBox' ? ( diff --git a/packages/utils-helpers/src/index.ts b/packages/utils-helpers/src/index.ts index c12402561c..a74b041952 100644 --- a/packages/utils-helpers/src/index.ts +++ b/packages/utils-helpers/src/index.ts @@ -8,6 +8,7 @@ import isEmail from './isEmail'; import {isUri} from './isUri'; import isEqualSet from './isEqualSet'; import isNil from './isNil'; +import svgToDataUri from './svgToDataUri'; export { decodeHtml, @@ -19,6 +20,7 @@ export { isEqualSet, stripTags, stripTagsEncoded, + svgToDataUri, cancelIdleCallback, requestIdleCallback }; diff --git a/packages/utils-helpers/src/svgToDataUri.ts b/packages/utils-helpers/src/svgToDataUri.ts new file mode 100644 index 0000000000..fcd0465bd7 --- /dev/null +++ b/packages/utils-helpers/src/svgToDataUri.ts @@ -0,0 +1,47 @@ +const REGEX = { + whitespace: /\s+/g, + urlHexPairs: /%[\dA-F]{2}/g, + quotes: /"/g +}; + +// Function to collapse whitespace in a string +const collapseWhitespace = (str: string): string => + str.trim().replace(REGEX.whitespace, ' '); + +// Function to encode data for a URI payload +const dataURIPayload = (string: string): string => + encodeURIComponent(string).replace(REGEX.urlHexPairs, specialHexEncode); + +// Function to handle special hex encoding +const specialHexEncode = (match: string): string => { + switch (match) { + case '%20': + return ' '; + case '%3D': + return '='; + case '%3A': + return ':'; + case '%2F': + return '/'; + default: + return match.toLowerCase(); // Compresses better + } +}; + +// Function to convert an SVG string to a tiny data URI +const svgToDataUri = (svgString: string): string => { + // Strip the Byte-Order Mark if the SVG has one + if (svgString.charCodeAt(0) === 0xfeff) { + svgString = svgString.slice(1); + } + + const body = collapseWhitespace(svgString); + return `data:image/svg+xml,${dataURIPayload(body)}`; +}; + +// Add a static method to handle srcset conversions +svgToDataUri.toSrcset = (svgString: string): string => + svgToDataUri(svgString).replace(/ /g, '%20'); + +// Export the function as the default export +export default svgToDataUri;