Skip to content

Commit b8ecc24

Browse files
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.
1 parent da8c62c commit b8ecc24

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

packages/neos-ui-ckeditor5-bindings/src/EditorToolbar/TableDropDown.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React, {PureComponent} from 'react';
33
import PropTypes from 'prop-types';
44

55
import {neos} from '@neos-project/neos-ui-decorators';
6+
import {svgToDataUri} from '@neos-project/utils-helpers';
67
import ckeIcons from './icons';
78

89
import style from './TableDropDown.module.css';
@@ -39,12 +40,14 @@ export default class TableDropDownButton extends PureComponent {
3940
}
4041

4142
render() {
43+
const iconDataUri = svgToDataUri(ckeIcons[this.props.icon]);
44+
console.log({iconDataUri});
4245
return (
4346
<DropDown
4447
padded={false}
4548
>
4649
<DropDown.Header title={this.props.i18nRegistry.translate(this.props.tooltip)}>
47-
<img style={{verticalAlign: 'text-top'}} src={ckeIcons[this.props.icon]} alt={this.props.i18nRegistry.translate(this.props.tooltip)} />
50+
<img style={{verticalAlign: 'text-top'}} src={iconDataUri} alt={this.props.i18nRegistry.translate(this.props.tooltip)} />
4851
</DropDown.Header>
4952
<DropDown.Contents className={style.contents} scrollable={false}>
5053
{this.props.options.map(item => item.type === 'checkBox' ? (

packages/utils-helpers/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import isEmail from './isEmail';
88
import {isUri} from './isUri';
99
import isEqualSet from './isEqualSet';
1010
import isNil from './isNil';
11+
import svgToDataUri from './svgToDataUri';
1112

1213
export {
1314
decodeHtml,
@@ -19,6 +20,7 @@ export {
1920
isEqualSet,
2021
stripTags,
2122
stripTagsEncoded,
23+
svgToDataUri,
2224
cancelIdleCallback,
2325
requestIdleCallback
2426
};
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const REGEX = {
2+
whitespace: /\s+/g,
3+
urlHexPairs: /%[\dA-F]{2}/g,
4+
quotes: /"/g
5+
};
6+
7+
// Function to collapse whitespace in a string
8+
const collapseWhitespace = (str: string): string =>
9+
str.trim().replace(REGEX.whitespace, ' ');
10+
11+
// Function to encode data for a URI payload
12+
const dataURIPayload = (string: string): string =>
13+
encodeURIComponent(string).replace(REGEX.urlHexPairs, specialHexEncode);
14+
15+
// Function to handle special hex encoding
16+
const specialHexEncode = (match: string): string => {
17+
switch (match) {
18+
case '%20':
19+
return ' ';
20+
case '%3D':
21+
return '=';
22+
case '%3A':
23+
return ':';
24+
case '%2F':
25+
return '/';
26+
default:
27+
return match.toLowerCase(); // Compresses better
28+
}
29+
};
30+
31+
// Function to convert an SVG string to a tiny data URI
32+
const svgToDataUri = (svgString: string): string => {
33+
// Strip the Byte-Order Mark if the SVG has one
34+
if (svgString.charCodeAt(0) === 0xfeff) {
35+
svgString = svgString.slice(1);
36+
}
37+
38+
const body = collapseWhitespace(svgString);
39+
return `data:image/svg+xml,${dataURIPayload(body)}`;
40+
};
41+
42+
// Add a static method to handle srcset conversions
43+
svgToDataUri.toSrcset = (svgString: string): string =>
44+
svgToDataUri(svgString).replace(/ /g, '%20');
45+
46+
// Export the function as the default export
47+
export default svgToDataUri;

0 commit comments

Comments
 (0)