Skip to content

Commit a183016

Browse files
committed
take Markdown rendering into account before testing the maximum preview length
1 parent b433663 commit a183016

File tree

3 files changed

+81
-19
lines changed

3 files changed

+81
-19
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
1212
- component for hiding elements in specific media
1313
- `<InlineText />`
1414
- force children to get displayed as inline content
15+
- `<StringPreviewContentBlobToggler />`
16+
- `useOnly` property: specify if only parts of the content should be used for the shortened preview, this property replaces `firstNonEmptyLineOnly`
1517

1618
### Fixed
1719

1820
- `<Tag />`
1921
- create more whitespace inside `small` tag
2022
- reduce visual impact of border
23+
- `<StringPreviewContentBlobToggler />`
24+
- take Markdown rendering into account before testing the maximum preview length
2125

2226
### Changed
2327

@@ -32,6 +36,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
3236
- `<GridColumn />`
3337
- `<PropertyName />` and `<PropertyValue />`
3438

39+
### Deprecated
40+
41+
- `<StringPreviewContentBlobToggler />`
42+
- `firstNonEmptyLineOnly` will be removed, is replaced by `useOnly="firstNonEmptyLine"`
43+
3544
## [25.0.0] - 2025-12-01
3645

3746
This is a major release, and it might be not compatible with your current usage of our library. Please read about the necessary changes in the section about how to migrate.

src/cmem/ContentBlobToggler/ContentBlobToggler.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export function ContentBlobToggler({
5858
{previewContent}
5959
{enableToggler && (
6060
<>
61-
&hellip;{" "}
61+
{" "}&hellip;{" "}
6262
<Link
6363
href="#more"
6464
data-test-id={"content-blob-toggler-more-link"}
Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,52 @@
11
import React from "react";
22

3-
import { ContentBlobToggler, ContentBlobTogglerProps, Markdown } from "./..";
3+
import {
4+
ContentBlobToggler,
5+
ContentBlobTogglerProps,
6+
Markdown,
7+
utils,
8+
InlineText,
9+
} from "./../../../index";
410

511
export interface StringPreviewContentBlobTogglerProps
612
extends Omit<ContentBlobTogglerProps, "previewContent" | "enableToggler"> {
713
/**
8-
The preview content will be cut to this length if it is too long.
14+
* The preview content will be cut to this length if it is too long.
915
*/
1016
previewMaxLength?: number;
1117
/**
12-
The content string. If it is smaller than previewMaxLength this will be displayed in full, else fullviewContent will be displayed.
18+
* The content string.
19+
* If it is smaller than `previewMaxLength` this will be displayed in full, else `fullviewContent` will be displayed.
1320
*/
1421
content: string;
15-
/** If only the first non-empty line should be shown in the preview. This will in addition also be shortened according to previewMaxLength. */
16-
firstNonEmptyLineOnly?: boolean;
17-
/** If enabled the preview is rendered as markdown. */
22+
/**
23+
* Use only parts of `content` in the preview.
24+
* `firstMarkdownSection` uses the content until the first double line return.
25+
* Currently overwritten by `firstNonEmptyLineOnly`.
26+
*/
27+
useOnly?: "firstNonEmptyLine" | "firstMarkdownSection";
28+
/**
29+
* If enabled the preview is rendered as Markdown.
30+
*/
1831
renderPreviewAsMarkdown?: boolean;
19-
/** White-listing of HTML elements that will be rendered when renderPreviewAsMarkdown is enabled. */
32+
/**
33+
* White-listing of HTML elements that will be rendered when renderPreviewAsMarkdown is enabled.
34+
*/
2035
allowedHtmlElementsInPreview?: string[];
21-
/** Allows to add non-string elements at the end of the content if the full description is shown, i.e. no toggler is necessary.
36+
/**
37+
* Allows to add non-string elements at the end of the content if the full description is shown, i.e. no toggler is necessary.
2238
* This allows to add non-string elements to both the full-view content and the pure string content.
2339
*/
2440
noTogglerContentSuffix?: JSX.Element;
41+
/**
42+
* If only the first non-empty line should be shown in the preview.
43+
* This will in addition also be shortened according to `previewMaxLength`.
44+
* @deprecated (v26) use `useOnly="firstNonEmptyLine"` instead
45+
*/
46+
firstNonEmptyLineOnly?: boolean;
2547
}
2648

27-
/** Version of the content toggler for text only content. */
49+
/** Version of the content toggler for text centric content. */
2850
export function StringPreviewContentBlobToggler({
2951
className = "",
3052
previewMaxLength,
@@ -33,21 +55,42 @@ export function StringPreviewContentBlobToggler({
3355
content,
3456
fullviewContent,
3557
startExtended,
36-
firstNonEmptyLineOnly,
58+
useOnly,
3759
renderPreviewAsMarkdown = false,
3860
allowedHtmlElementsInPreview,
3961
noTogglerContentSuffix,
62+
firstNonEmptyLineOnly,
4063
}: StringPreviewContentBlobTogglerProps) {
41-
const previewMaybeFirstLine = firstNonEmptyLineOnly ? firstNonEmptyLine(content) : content;
42-
const previewString = previewMaxLength ? previewMaybeFirstLine.substr(0, previewMaxLength) : previewMaybeFirstLine;
43-
const enableToggler = previewString !== content;
64+
// need to test `firstNonEmptyLineOnly` until property is removed
65+
const useOnlyTest: StringPreviewContentBlobTogglerProps["useOnly"] = firstNonEmptyLineOnly ? "firstNonEmptyLine" : useOnly;
66+
67+
let previewString = content;
68+
switch (useOnlyTest) {
69+
case "firstNonEmptyLine":
70+
previewString = useOnlyPart(content, regexFirstNonEmptyLine);
71+
break;
72+
case "firstMarkdownSection":
73+
previewString = useOnlyPart(content, regexFirstMarkdownSection);
74+
}
75+
76+
let enableToggler = previewString !== content;
77+
4478
let previewContent = renderPreviewAsMarkdown ? (
4579
<Markdown key="markdown-content" allowedElements={allowedHtmlElementsInPreview}>
4680
{previewString}
4781
</Markdown>
4882
) : (
4983
previewString
5084
);
85+
86+
if (
87+
previewMaxLength &&
88+
utils.reduceToText(previewContent, { decodeHtmlEntities: true }).length > previewMaxLength
89+
) {
90+
previewContent = utils.reduceToText(previewContent, { decodeHtmlEntities: true }).slice(0, previewMaxLength);
91+
enableToggler = true;
92+
}
93+
5194
if (!enableToggler && noTogglerContentSuffix) {
5295
previewContent = (
5396
<>
@@ -60,7 +103,7 @@ export function StringPreviewContentBlobToggler({
60103
return (
61104
<ContentBlobToggler
62105
className={className}
63-
previewContent={previewContent}
106+
previewContent={<InlineText>{previewContent}</InlineText>}
64107
toggleExtendText={toggleExtendText}
65108
toggleReduceText={toggleReduceText}
66109
fullviewContent={fullviewContent}
@@ -70,17 +113,27 @@ export function StringPreviewContentBlobToggler({
70113
);
71114
}
72115

73-
const newLineRegex = new RegExp("\r|\n"); // eslint-disable-line
116+
const regexFirstNonEmptyLine = new RegExp("\r|\n"); // eslint-disable-line
117+
const regexFirstMarkdownSection = new RegExp("\r\n\r\n|\n\n"); // eslint-disable-line
74118

75119
/**
76120
* Takes the first non-empty line from a preview string.
77121
*/
78122
function firstNonEmptyLine(preview: string) {
123+
return useOnlyPart(preview, regexFirstNonEmptyLine)
124+
}
125+
126+
/**
127+
* Returns only the first part from a preview string.
128+
* Or the full string as fallback.
129+
*/
130+
function useOnlyPart(preview: string, regexTest: RegExp): string {
79131
const previewString = preview.trim();
80-
const result = newLineRegex.exec(previewString);
81-
return result !== null ? previewString.substr(0, result.index) : previewString;
132+
const result = regexTest.exec(previewString);
133+
return result !== null ? result.input.slice(0, result.index) : previewString;
82134
}
83135

136+
84137
export const stringPreviewContentBlobTogglerUtils = {
85138
firstNonEmptyLine,
86-
};
139+
};

0 commit comments

Comments
 (0)