Skip to content

Commit

Permalink
enable parsing html in timeline items
Browse files Browse the repository at this point in the history
  • Loading branch information
prabhuignoto committed Jan 4, 2024
1 parent 6f9c350 commit d448830
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 24 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"classnames": "^2.5.1",
"dayjs": "^1.11.10",
"focus-visible": "^5.2.0",
"sanitize-html": "^2.11.0",
"styled-components": "^6.1.6",
"stylis": "^4.3.1"
},
Expand Down Expand Up @@ -81,6 +82,7 @@
"@types/react": "^18.2.46",
"@types/react-dom": "^18.2.18",
"@types/react-router-dom": "^5.3.3",
"@types/sanitize-html": "^2.9.5",
"@types/styled-components": "^5.1.34",
"@types/testing-library__jest-dom": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^6.17.0",
Expand Down
44 changes: 35 additions & 9 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/components/GlobalContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const GlobalContextProvider: FunctionComponent<Partial<PropsModel>> = (
lineWidth: 3,
mediaHeight: 200,
nestedCardHeight: 150,
parseDetailsTextHTML: false,
scrollable: {
scrollbar: false,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { TimelineContentModel } from '@models/TimelineContentModel';
import { ForwardRefExoticComponent, forwardRef, useContext } from 'react';
import sanitizeHtml from 'sanitize-html';
import { GlobalContext } from '../../GlobalContext';
import {
TimelineSubContent,
TimelineContentDetails,
TimelineSubContent,
} from './timeline-card-content.styles';

export type TextOrContentModel = Pick<
Expand All @@ -26,34 +27,69 @@ const getTextOrContent: (
// const { timelineContent, theme, detailedText, showMore } = prop;
const isTextArray = Array.isArray(detailedText);

const { fontSizes, classNames } = useContext(GlobalContext);
const { fontSizes, classNames, parseDetailsTextHTML } =
useContext(GlobalContext);

if (timelineContent) {
return <div ref={ref}>{timelineContent}</div>;
} else {
let textContent = null;
if (isTextArray) {
textContent = (detailedText as string[]).map((text, index) => (
<TimelineSubContent
key={index}
fontSize={fontSizes?.cardText}
className={classNames?.cardText}
theme={theme}
>
{text}
</TimelineSubContent>
));
textContent = (detailedText as string[]).map((text, index) => {
const props = parseDetailsTextHTML
? {
dangerouslySetInnerHTML: {
__html: sanitizeHtml(text, {
parseStyleAttributes: true,
}),
},
}
: null;
console.log(props);
return (
<TimelineSubContent
key={index}
fontSize={fontSizes?.cardText}
className={classNames?.cardText}
theme={theme}
{...props}
// dangerouslySetInnerHTML={{
// __html: sanitizeHtml(text, {
// parseStyleAttributes: true,
// }),
// }}
>
{parseDetailsTextHTML ? null : text}
</TimelineSubContent>
);
});
} else {
textContent = detailedText;
textContent = parseDetailsTextHTML
? sanitizeHtml(detailedText, {
parseStyleAttributes: true,
})
: detailedText;
}

const textContentProps =
parseDetailsTextHTML && !isTextArray
? {
dangerouslySetInnerHTML: {
__html: sanitizeHtml(textContent, {
parseStyleAttributes: true,
}),
},
}
: {};

return textContent ? (
<TimelineContentDetails
className={showMore ? 'active' : ''}
ref={ref}
theme={theme}
{...textContentProps}
>
{textContent}
{parseDetailsTextHTML && !isTextArray ? null : textContent}
</TimelineContentDetails>
) : null;
}
Expand Down
10 changes: 9 additions & 1 deletion src/demo/data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ const items: TimelineItemModel[] = [
'Men of the British Expeditionary Force (BEF) wade out to a destroyer during the evacuation from Dunkirk.',
// cardDetailedText: [`On 10 May 1940, Hitler began his long-awaited offensive in the west by invading neutral Holland and Belgium and attacking northern France.`, `Holland capitulated after only five days of fighting, and the Belgians surrendered on 28 May. With the success of the German ‘Blitzkrieg’, the British Expeditionary Force and French troops were in danger of being cut off and destroyed.`],
cardDetailedText: [
`On 10 May 1940, Hitler began his long-awaited offensive in the west by invading neutral Holland and Belgium and attacking northern France.`,
`On 10 May 1940, <a href="http://www.google.com">Hitler</a> began his <strong>long-awaited</strong> offensive in the west by invading neutral Holland and Belgium and attacking northern France.
<br>`,
`<ul>
<li>Holland capitulated after only five days of fighting, and the Belgians surrendered on 28 May.</li>
<li>With the success of the German ‘Blitzkrieg’, the British Expeditionary Force and French troops were in danger of being cut off and destroyed.</li>
</ul>
`,
],
// cardDetailedText: `Holland capitulated <a href="www.google.com">the</a> after <b>only</b> five days of fighting, and the Belgians surrendered on 28 May.With the success of the German ‘Blitzkrieg’, the British Expeditionary Force and French troops were in danger of being cut off and destroyed.`,
},
{
title: '25 July 1941',
Expand All @@ -32,6 +39,7 @@ const items: TimelineItemModel[] = [
},
type: 'IMAGE',
},

// items: [
// {
// cardTitle: 'The Battle of Britian Yaar',
Expand Down
1 change: 1 addition & 0 deletions src/demo/vertical-samples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export const VerticalBasic: FunctionComponent<{
noUniqueId
disableTimelinePoint
uniqueID="vertical_basic_test"
parseDetailsTextHTML
// textOverlay
// borderLessCards
// theme={{
Expand Down
1 change: 1 addition & 0 deletions src/models/TimelineMediaModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export interface CardMediaModel {
content?: string | ReactNode;

// Text details associated with the media.
// detailsText?: ForwardRefExoticComponent<TextOrContentModel>;
detailsText?: ForwardRefExoticComponent<TextOrContentModel>;

// Indicates if media should be hidden.
Expand Down
2 changes: 2 additions & 0 deletions src/models/TimelineModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ export type TimelineProps = {

onThemeChange?: () => void;

parseDetailsTextHTML?: boolean;

// option to enable scrollbar
scrollable?: boolean | { scrollbar: boolean };

Expand Down
12 changes: 12 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SlideShowType, TimelineMode } from '@models/TimelineModel';
import { darkTheme, defaultTheme } from '../components/common/themes';
import santizeHtml from 'sanitize-html';

export const uniqueID = () => {
const chars =
Expand Down Expand Up @@ -65,3 +66,14 @@ export const getSlideShowType: (mode: TimelineMode) => SlideShowType = (

return 'reveal';
};

export const isTextArray = (text: string | string[]): text is string[] => {
return Array.isArray(text);
}

export const sanitizeHtmlText = (text: string | string[]) => {
if (isTextArray(text)) {
return text.map((t) => santizeHtml(t));
}
return santizeHtml(text);
}

0 comments on commit d448830

Please sign in to comment.