@gravity-ui/page-constructor 5.28.7-alpha.0 → 5.28.7-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,9 +8,10 @@ const MediaBase_1 = tslib_1.__importDefault(require("../../components/MediaBase/
8
8
  const theme_1 = require("../../context/theme");
9
9
  const utils_1 = require("../../utils");
10
10
  const borderSelector_1 = require("../../utils/borderSelector");
11
+ const microdata_1 = require("../../utils/microdata");
11
12
  const b = (0, utils_1.block)('media-block');
12
13
  const MediaBlock = (props) => {
13
- const { media, border, disableShadow } = props;
14
+ const { media, border, disableShadow, title, description } = props;
14
15
  const borderSelected = (0, borderSelector_1.getMediaBorder)({
15
16
  border,
16
17
  disableShadow,
@@ -18,9 +19,13 @@ const MediaBlock = (props) => {
18
19
  const [play, setPlay] = (0, react_1.useState)(false);
19
20
  const theme = (0, theme_1.useTheme)();
20
21
  const mediaThemed = (0, utils_1.getThemedValue)(media, theme);
22
+ const mediaWithMicrodata = (0, microdata_1.mergeVideoMicrodata)(mediaThemed, {
23
+ name: (0, microdata_1.sanitizeMicrodata)(title),
24
+ description: description ? (0, microdata_1.sanitizeMicrodata)(description) : undefined,
25
+ });
21
26
  return (react_1.default.createElement(MediaBase_1.default, Object.assign({}, props, { onScroll: () => setPlay(true) }),
22
27
  react_1.default.createElement(MediaBase_1.default.Card, null,
23
- react_1.default.createElement(Media_1.default, Object.assign({ imageClassName: b('image') }, mediaThemed, { playVideo: play, className: b({ border: borderSelected }) })))));
28
+ react_1.default.createElement(Media_1.default, Object.assign({ imageClassName: b('image') }, mediaWithMicrodata, { playVideo: play, className: b({ border: borderSelected }) })))));
24
29
  };
25
30
  exports.MediaBlock = MediaBlock;
26
31
  exports.default = exports.MediaBlock;
@@ -30,8 +30,8 @@ const PromoFeaturesBlock = (props) => {
30
30
  const themeMod = cardTheme || blockModifier || '';
31
31
  const themedMedia = (0, utils_1.getThemedValue)(media, globalTheme);
32
32
  const allProps = (0, microdata_1.mergeVideoMicrodata)(themedMedia, {
33
- name: cardTitle,
34
- description: text,
33
+ name: (0, microdata_1.sanitizeMicrodata)(cardTitle),
34
+ description: (0, microdata_1.sanitizeMicrodata)(text),
35
35
  });
36
36
  return (react_1.default.createElement("div", { key: index, className: b('card', {
37
37
  'no-media': !media,
@@ -64,7 +64,7 @@ const TabsBlock = ({ items, title, description, animated, tabsColSizes, centered
64
64
  const showMedia = Boolean((activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.media) || imageProps);
65
65
  const showText = Boolean(activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.text);
66
66
  const border = (activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.border) || 'shadow';
67
- const textContent = activeTabData && showText && (react_1.default.createElement(TabsTextContent_1.default, { showMedia: showMedia, data: activeTabData, imageProps: imageProps ? imageProps : undefined, isReverse: isReverse, contentSize: contentSize, centered: centered }));
67
+ const textContent = showText && (react_1.default.createElement(TabsTextContent_1.default, { showMedia: showMedia, data: activeTabData, imageProps: imageProps ? imageProps : undefined, isReverse: isReverse, contentSize: contentSize, centered: centered }));
68
68
  const mediaContent = showMedia && (react_1.default.createElement(grid_1.Col, { sizes: { all: 12, md: 8 }, orders: {
69
69
  all: grid_1.GridColumnOrderClasses.Last,
70
70
  md: grid_1.GridColumnOrderClasses.First,
@@ -73,7 +73,9 @@ const TabsBlock = ({ items, title, description, animated, tabsColSizes, centered
73
73
  react_1.default.createElement("div", { ref: ref },
74
74
  react_1.default.createElement(Media_1.default, Object.assign({}, (0, microdata_1.mergeVideoMicrodata)((0, utils_2.getThemedValue)(activeTabData.media, theme), {
75
75
  name: activeTabData.tabName,
76
- description: activeTabData.caption,
76
+ description: activeTabData.caption
77
+ ? (0, microdata_1.sanitizeMicrodata)(activeTabData.caption)
78
+ : undefined,
77
79
  }), { key: activeTab, className: b('media', { border }), playVideo: play, height: mediaVideoHeight || undefined, onImageLoad: handleImageHeight }))))),
78
80
  imageProps && (react_1.default.createElement(react_1.Fragment, null,
79
81
  react_1.default.createElement(FullscreenImage_1.default, Object.assign({}, imageProps, { imageClassName: b('image', { border }) })))),
@@ -2,9 +2,9 @@ import { ImageDeviceProps, ImageObjectProps, TabsBlockItem, TabsBlockProps } fro
2
2
  interface TextContentProps extends Pick<TabsBlockProps, 'centered' | 'contentSize'> {
3
3
  showMedia: boolean;
4
4
  isReverse: boolean;
5
- data: TabsBlockItem;
5
+ data?: TabsBlockItem;
6
6
  centered?: boolean;
7
7
  imageProps?: ImageObjectProps | ImageDeviceProps;
8
8
  }
9
- export declare const TabsTextContent: ({ centered, contentSize, showMedia, data: { media, title, text, additionalInfo, link, links, buttons, list }, imageProps, isReverse, }: TextContentProps) => JSX.Element;
9
+ export declare const TabsTextContent: ({ centered, contentSize, showMedia, data, imageProps, isReverse, }: TextContentProps) => JSX.Element | null;
10
10
  export default TabsTextContent;
@@ -7,11 +7,17 @@ const grid_1 = require("../../../grid");
7
7
  const sub_blocks_1 = require("../../../sub-blocks");
8
8
  const utils_1 = require("../../../utils");
9
9
  const b = (0, utils_1.block)('tabs-block-text-content');
10
- const TabsTextContent = ({ centered, contentSize = 's', showMedia, data: { media, title, text, additionalInfo, link, links, buttons, list }, imageProps, isReverse, }) => (react_1.default.createElement(grid_1.Col, { sizes: { all: 12, md: showMedia ? 4 : 8 }, className: b({ centered: centered }) },
11
- react_1.default.createElement("div", { className: b('wrapper', {
12
- reverse: isReverse,
13
- 'no-image': !(media || imageProps),
14
- }) },
15
- react_1.default.createElement(sub_blocks_1.Content, { title: title, text: text, additionalInfo: additionalInfo, size: contentSize, list: list, links: [...(link ? [link] : []), ...(links || [])], buttons: buttons, colSizes: { all: 12 } }))));
10
+ const TabsTextContent = ({ centered, contentSize = 's', showMedia, data, imageProps, isReverse, }) => {
11
+ if (!data) {
12
+ return null;
13
+ }
14
+ const { media, title, text, additionalInfo, link, links, buttons, list } = data;
15
+ return (react_1.default.createElement(grid_1.Col, { sizes: { all: 12, md: showMedia ? 4 : 8 }, className: b({ centered: centered }) },
16
+ react_1.default.createElement("div", { className: b('wrapper', {
17
+ reverse: isReverse,
18
+ 'no-image': !(media || imageProps),
19
+ }) },
20
+ react_1.default.createElement(sub_blocks_1.Content, { title: title, text: text, additionalInfo: additionalInfo, size: contentSize, list: list, links: [...(link ? [link] : []), ...(links || [])], buttons: buttons, colSizes: { all: 12 } }))));
21
+ };
16
22
  exports.TabsTextContent = TabsTextContent;
17
23
  exports.default = exports.TabsTextContent;
@@ -19,19 +19,20 @@ const LayoutItem = (_a) => {
19
19
  const contentProps = Object.assign(Object.assign({ controlPosition: areControlsInFooter ? 'bottom' : 'default' }, content), { links: normalizedLinks, size: 's', colSizes: { all: 12, md: 12 } });
20
20
  const titleId = (0, uikit_1.useUniqId)();
21
21
  const renderMedia = () => {
22
+ var _a;
22
23
  if (!media) {
23
24
  return null;
24
25
  }
25
26
  const themedMedia = (0, utils_1.getThemedValue)(media, theme);
27
+ const mediaWithMicrodata = (0, microdata_1.mergeVideoMicrodata)(themedMedia, {
28
+ name: typeof content.title === 'string'
29
+ ? (0, microdata_1.sanitizeMicrodata)(content.title)
30
+ : (0, microdata_1.sanitizeMicrodata)(((_a = content.title) === null || _a === void 0 ? void 0 : _a.text) || ''),
31
+ description: content.text ? (0, microdata_1.sanitizeMicrodata)(content.text) : undefined,
32
+ });
26
33
  return fullscreen && (0, utils_2.hasFullscreen)(themedMedia) ? (react_1.default.createElement(components_1.FullscreenMedia, { showFullscreenIcon: (0, utils_2.showFullscreenIcon)(themedMedia) }, (_a = {}) => {
27
- var _b;
28
34
  var { className: mediaClassName, fullscreen: _fullscreen } = _a, fullscreenMediaProps = tslib_1.__rest(_a, ["className", "fullscreen"]);
29
- return (react_1.default.createElement(components_1.Media, Object.assign({}, (0, microdata_1.mergeVideoMicrodata)(themedMedia, {
30
- name: typeof content.title === 'string'
31
- ? content.title
32
- : (_b = content.title) === null || _b === void 0 ? void 0 : _b.text,
33
- description: content.text,
34
- }), fullscreenMediaProps, { className: b('media', { border }, mediaClassName), analyticsEvents: analyticsEvents })));
35
+ return (react_1.default.createElement(components_1.Media, Object.assign({}, mediaWithMicrodata, fullscreenMediaProps, { className: b('media', { border }, mediaClassName), analyticsEvents: analyticsEvents })));
35
36
  })) : (react_1.default.createElement(components_1.Media, Object.assign({}, themedMedia, { className: b('media', { border }), analyticsEvents: analyticsEvents })));
36
37
  };
37
38
  return (react_1.default.createElement("div", { className: b(null, className) },
@@ -1,2 +1,3 @@
1
1
  import { MediaProps } from '../models';
2
2
  export declare const mergeVideoMicrodata: (values?: MediaProps, newValues?: MediaProps['videoMicrodata']) => MediaProps;
3
+ export declare function sanitizeMicrodata(html: string): string;
@@ -1,5 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mergeVideoMicrodata = void 0;
3
+ exports.sanitizeMicrodata = exports.mergeVideoMicrodata = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const sanitize_html_1 = tslib_1.__importDefault(require("sanitize-html"));
4
6
  const mergeVideoMicrodata = (values = {}, newValues = {}) => (Object.assign(Object.assign({}, values), { videoMicrodata: Object.assign(Object.assign({}, newValues), (values.videoMicrodata || {})) }));
5
7
  exports.mergeVideoMicrodata = mergeVideoMicrodata;
8
+ function sanitizeMicrodata(html) {
9
+ return html && (0, sanitize_html_1.default)(html, { allowedTags: [], allowedAttributes: {} });
10
+ }
11
+ exports.sanitizeMicrodata = sanitizeMicrodata;
@@ -4,10 +4,11 @@ import MediaBase from '../../components/MediaBase/MediaBase';
4
4
  import { useTheme } from '../../context/theme';
5
5
  import { block, getThemedValue } from '../../utils';
6
6
  import { getMediaBorder } from '../../utils/borderSelector';
7
+ import { mergeVideoMicrodata, sanitizeMicrodata } from '../../utils/microdata';
7
8
  import './Media.css';
8
9
  const b = block('media-block');
9
10
  export const MediaBlock = (props) => {
10
- const { media, border, disableShadow } = props;
11
+ const { media, border, disableShadow, title, description } = props;
11
12
  const borderSelected = getMediaBorder({
12
13
  border,
13
14
  disableShadow,
@@ -15,8 +16,12 @@ export const MediaBlock = (props) => {
15
16
  const [play, setPlay] = useState(false);
16
17
  const theme = useTheme();
17
18
  const mediaThemed = getThemedValue(media, theme);
19
+ const mediaWithMicrodata = mergeVideoMicrodata(mediaThemed, {
20
+ name: sanitizeMicrodata(title),
21
+ description: description ? sanitizeMicrodata(description) : undefined,
22
+ });
18
23
  return (React.createElement(MediaBase, Object.assign({}, props, { onScroll: () => setPlay(true) }),
19
24
  React.createElement(MediaBase.Card, null,
20
- React.createElement(Media, Object.assign({ imageClassName: b('image') }, mediaThemed, { playVideo: play, className: b({ border: borderSelected }) })))));
25
+ React.createElement(Media, Object.assign({ imageClassName: b('image') }, mediaWithMicrodata, { playVideo: play, className: b({ border: borderSelected }) })))));
21
26
  };
22
27
  export default MediaBlock;
@@ -8,7 +8,7 @@ import YFMWrapper from '../../components/YFMWrapper/YFMWrapper';
8
8
  import { BREAKPOINTS } from '../../constants';
9
9
  import { useTheme } from '../../context/theme';
10
10
  import { block, getThemedValue } from '../../utils';
11
- import { mergeVideoMicrodata } from '../../utils/microdata';
11
+ import { mergeVideoMicrodata, sanitizeMicrodata } from '../../utils/microdata';
12
12
  import './PromoFeaturesBlock.css';
13
13
  const b = block('PromoFeaturesBlock');
14
14
  const breakpointColumns = {
@@ -28,8 +28,8 @@ const PromoFeaturesBlock = (props) => {
28
28
  const themeMod = cardTheme || blockModifier || '';
29
29
  const themedMedia = getThemedValue(media, globalTheme);
30
30
  const allProps = mergeVideoMicrodata(themedMedia, {
31
- name: cardTitle,
32
- description: text,
31
+ name: sanitizeMicrodata(cardTitle),
32
+ description: sanitizeMicrodata(text),
33
33
  });
34
34
  return (React.createElement("div", { key: index, className: b('card', {
35
35
  'no-media': !media,
@@ -11,7 +11,7 @@ import YFMWrapper from '../../components/YFMWrapper/YFMWrapper';
11
11
  import { useTheme } from '../../context/theme';
12
12
  import { Col, GridColumnOrderClasses, Row } from '../../grid';
13
13
  import { block, getThemedValue } from '../../utils';
14
- import { mergeVideoMicrodata } from '../../utils/microdata';
14
+ import { mergeVideoMicrodata, sanitizeMicrodata } from '../../utils/microdata';
15
15
  import TabsTextContent from './TabsTextContent/TabsTextContent';
16
16
  import './Tabs.css';
17
17
  const b = block('tabs-block');
@@ -61,7 +61,7 @@ export const TabsBlock = ({ items, title, description, animated, tabsColSizes, c
61
61
  const showMedia = Boolean((activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.media) || imageProps);
62
62
  const showText = Boolean(activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.text);
63
63
  const border = (activeTabData === null || activeTabData === void 0 ? void 0 : activeTabData.border) || 'shadow';
64
- const textContent = activeTabData && showText && (React.createElement(TabsTextContent, { showMedia: showMedia, data: activeTabData, imageProps: imageProps ? imageProps : undefined, isReverse: isReverse, contentSize: contentSize, centered: centered }));
64
+ const textContent = showText && (React.createElement(TabsTextContent, { showMedia: showMedia, data: activeTabData, imageProps: imageProps ? imageProps : undefined, isReverse: isReverse, contentSize: contentSize, centered: centered }));
65
65
  const mediaContent = showMedia && (React.createElement(Col, { sizes: { all: 12, md: 8 }, orders: {
66
66
  all: GridColumnOrderClasses.Last,
67
67
  md: GridColumnOrderClasses.First,
@@ -70,7 +70,9 @@ export const TabsBlock = ({ items, title, description, animated, tabsColSizes, c
70
70
  React.createElement("div", { ref: ref },
71
71
  React.createElement(Media, Object.assign({}, mergeVideoMicrodata(getThemedValue(activeTabData.media, theme), {
72
72
  name: activeTabData.tabName,
73
- description: activeTabData.caption,
73
+ description: activeTabData.caption
74
+ ? sanitizeMicrodata(activeTabData.caption)
75
+ : undefined,
74
76
  }), { key: activeTab, className: b('media', { border }), playVideo: play, height: mediaVideoHeight || undefined, onImageLoad: handleImageHeight }))))),
75
77
  imageProps && (React.createElement(Fragment, null,
76
78
  React.createElement(FullscreenImage, Object.assign({}, imageProps, { imageClassName: b('image', { border }) })))),
@@ -3,9 +3,9 @@ import './TabsTextContent.css';
3
3
  interface TextContentProps extends Pick<TabsBlockProps, 'centered' | 'contentSize'> {
4
4
  showMedia: boolean;
5
5
  isReverse: boolean;
6
- data: TabsBlockItem;
6
+ data?: TabsBlockItem;
7
7
  centered?: boolean;
8
8
  imageProps?: ImageObjectProps | ImageDeviceProps;
9
9
  }
10
- export declare const TabsTextContent: ({ centered, contentSize, showMedia, data: { media, title, text, additionalInfo, link, links, buttons, list }, imageProps, isReverse, }: TextContentProps) => JSX.Element;
10
+ export declare const TabsTextContent: ({ centered, contentSize, showMedia, data, imageProps, isReverse, }: TextContentProps) => JSX.Element | null;
11
11
  export default TabsTextContent;
@@ -4,10 +4,16 @@ import { Content } from '../../../sub-blocks';
4
4
  import { block } from '../../../utils';
5
5
  import './TabsTextContent.css';
6
6
  const b = block('tabs-block-text-content');
7
- export const TabsTextContent = ({ centered, contentSize = 's', showMedia, data: { media, title, text, additionalInfo, link, links, buttons, list }, imageProps, isReverse, }) => (React.createElement(Col, { sizes: { all: 12, md: showMedia ? 4 : 8 }, className: b({ centered: centered }) },
8
- React.createElement("div", { className: b('wrapper', {
9
- reverse: isReverse,
10
- 'no-image': !(media || imageProps),
11
- }) },
12
- React.createElement(Content, { title: title, text: text, additionalInfo: additionalInfo, size: contentSize, list: list, links: [...(link ? [link] : []), ...(links || [])], buttons: buttons, colSizes: { all: 12 } }))));
7
+ export const TabsTextContent = ({ centered, contentSize = 's', showMedia, data, imageProps, isReverse, }) => {
8
+ if (!data) {
9
+ return null;
10
+ }
11
+ const { media, title, text, additionalInfo, link, links, buttons, list } = data;
12
+ return (React.createElement(Col, { sizes: { all: 12, md: showMedia ? 4 : 8 }, className: b({ centered: centered }) },
13
+ React.createElement("div", { className: b('wrapper', {
14
+ reverse: isReverse,
15
+ 'no-image': !(media || imageProps),
16
+ }) },
17
+ React.createElement(Content, { title: title, text: text, additionalInfo: additionalInfo, size: contentSize, list: list, links: [...(link ? [link] : []), ...(links || [])], buttons: buttons, colSizes: { all: 12 } }))));
18
+ };
13
19
  export default TabsTextContent;
@@ -4,7 +4,7 @@ import { useUniqId } from '@gravity-ui/uikit';
4
4
  import { FullscreenMedia, IconWrapper, Media, MetaInfo } from '../../components';
5
5
  import { useTheme } from '../../context/theme';
6
6
  import { block, getThemedValue } from '../../utils';
7
- import { mergeVideoMicrodata } from '../../utils/microdata';
7
+ import { mergeVideoMicrodata, sanitizeMicrodata } from '../../utils/microdata';
8
8
  import Content from '../Content/Content';
9
9
  import { getLayoutItemLinks, hasFullscreen, showFullscreenIcon } from './utils';
10
10
  import './LayoutItem.css';
@@ -18,19 +18,20 @@ const LayoutItem = (_a) => {
18
18
  const contentProps = Object.assign(Object.assign({ controlPosition: areControlsInFooter ? 'bottom' : 'default' }, content), { links: normalizedLinks, size: 's', colSizes: { all: 12, md: 12 } });
19
19
  const titleId = useUniqId();
20
20
  const renderMedia = () => {
21
+ var _a;
21
22
  if (!media) {
22
23
  return null;
23
24
  }
24
25
  const themedMedia = getThemedValue(media, theme);
26
+ const mediaWithMicrodata = mergeVideoMicrodata(themedMedia, {
27
+ name: typeof content.title === 'string'
28
+ ? sanitizeMicrodata(content.title)
29
+ : sanitizeMicrodata(((_a = content.title) === null || _a === void 0 ? void 0 : _a.text) || ''),
30
+ description: content.text ? sanitizeMicrodata(content.text) : undefined,
31
+ });
25
32
  return fullscreen && hasFullscreen(themedMedia) ? (React.createElement(FullscreenMedia, { showFullscreenIcon: showFullscreenIcon(themedMedia) }, (_a = {}) => {
26
- var _b;
27
33
  var { className: mediaClassName, fullscreen: _fullscreen } = _a, fullscreenMediaProps = __rest(_a, ["className", "fullscreen"]);
28
- return (React.createElement(Media, Object.assign({}, mergeVideoMicrodata(themedMedia, {
29
- name: typeof content.title === 'string'
30
- ? content.title
31
- : (_b = content.title) === null || _b === void 0 ? void 0 : _b.text,
32
- description: content.text,
33
- }), fullscreenMediaProps, { className: b('media', { border }, mediaClassName), analyticsEvents: analyticsEvents })));
34
+ return (React.createElement(Media, Object.assign({}, mediaWithMicrodata, fullscreenMediaProps, { className: b('media', { border }, mediaClassName), analyticsEvents: analyticsEvents })));
34
35
  })) : (React.createElement(Media, Object.assign({}, themedMedia, { className: b('media', { border }), analyticsEvents: analyticsEvents })));
35
36
  };
36
37
  return (React.createElement("div", { className: b(null, className) },
@@ -1,2 +1,3 @@
1
1
  import { MediaProps } from '../models';
2
2
  export declare const mergeVideoMicrodata: (values?: MediaProps, newValues?: MediaProps['videoMicrodata']) => MediaProps;
3
+ export declare function sanitizeMicrodata(html: string): string;
@@ -1 +1,5 @@
1
+ import sanitize from 'sanitize-html';
1
2
  export const mergeVideoMicrodata = (values = {}, newValues = {}) => (Object.assign(Object.assign({}, values), { videoMicrodata: Object.assign(Object.assign({}, newValues), (values.videoMicrodata || {})) }));
3
+ export function sanitizeMicrodata(html) {
4
+ return html && sanitize(html, { allowedTags: [], allowedAttributes: {} });
5
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/page-constructor",
3
- "version": "5.28.7-alpha.0",
3
+ "version": "5.28.7-alpha.3",
4
4
  "description": "Gravity UI Page Constructor",
5
5
  "license": "MIT",
6
6
  "repository": {