Skip to content

Commit 2e901f9

Browse files
committed
feat(): Adding the article viewer feature
1 parent be66a2d commit 2e901f9

23 files changed

Lines changed: 1139 additions & 32 deletions

File tree

jest.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,9 @@ jest.mock('@fontsource/space-mono', () => {
2525
default: jest.fn(),
2626
};
2727
});
28+
29+
// React markdown preview mock.
30+
jest.mock('@uiw/react-markdown-preview', () => ({
31+
__esModule: true,
32+
default: 'markdown-preview',
33+
}));

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"@types/node": "^16.18.91",
4545
"@types/react": "^18.2.69",
4646
"@types/react-dom": "^18.2.22",
47+
"@uiw/react-markdown-preview": "^5.1.3",
4748
"axios": "^1.7.9",
4849
"framer-motion": "^11.1.9",
4950
"fuse.js": "^7.0.0",

src/components/ArticleCard/ArticleCard.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { Box, HStack, Img, Text } from '@chakra-ui/react';
2+
import { useEffect } from 'react';
3+
import { useNavigate } from 'react-router-dom';
4+
import { useCursor } from '../Cursor';
25

36
type ArticleCardProps = {
7+
article_key: string;
48
title: string;
59
image: string;
610
description: string;
@@ -11,6 +15,7 @@ type ArticleCardProps = {
1115
};
1216

1317
const ArticleCard = ({
18+
article_key,
1419
title,
1520
last_updated,
1621
image,
@@ -19,14 +24,28 @@ const ArticleCard = ({
1924
views,
2025
likes,
2126
}: ArticleCardProps) => {
27+
const navigation = useNavigate();
28+
const { setCursorType } = useCursor();
29+
useEffect(() => {
30+
setCursorType('none');
31+
}, [setCursorType]);
32+
2233
return (
2334
<Box
24-
bg={'black'}
35+
zIndex={1}
36+
_hover={{
37+
transform: 'scale(1.02)',
38+
cursor: 'pointer',
39+
}}
40+
transition={'all 0.4s ease'}
41+
bg={'rgba(0, 0, 0, 0.4)'}
42+
backdropFilter={'blur(10px)'}
2543
padding={4}
2644
borderRadius={10}
27-
border={'1px solid #ffffffa0'}
45+
border={'1px solid gray'}
2846
width={'300px'}
2947
color={'white'}
48+
onClick={() => navigation(article_key)}
3049
>
3150
<Text fontSize="2xl" fontWeight="bold" color="brand.900" marginBottom={2}>
3251
{title}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Box } from '@chakra-ui/react';
2+
import MarkdownPreview from '@uiw/react-markdown-preview';
3+
import markdownStyle from './css/Markdown.module.css';
4+
import { MdPreviewProps } from './types';
5+
6+
const MdPreview = ({ mdString }: MdPreviewProps) => {
7+
return (
8+
<Box width={'100%'} maxW={'70vw'} data-color-mode={'dark'}>
9+
<MarkdownPreview className={markdownStyle.markdown} source={mdString} />
10+
</Box>
11+
);
12+
};
13+
14+
export default MdPreview;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import MdPreview from '../MdPreview';
2+
import { render } from '@testing-library/react';
3+
4+
describe('MdPreview', () => {
5+
it('should render MdPreview', () => {
6+
const { container } = render(
7+
<MdPreview mdString={''} variant={'withSide'} />,
8+
);
9+
expect(container).toMatchSnapshot();
10+
});
11+
12+
it('should render MdPreview', () => {
13+
const { container } = render(
14+
<MdPreview mdString={'test'} variant={'withoutSide'} />,
15+
);
16+
expect(container).toMatchSnapshot();
17+
});
18+
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`MdPreview should render MdPreview 1`] = `
4+
<div>
5+
<div
6+
class="css-1npfbn5"
7+
data-color-mode="dark"
8+
>
9+
<markdown-preview
10+
source=""
11+
/>
12+
</div>
13+
</div>
14+
`;
15+
16+
exports[`MdPreview should render MdPreview 2`] = `
17+
<div>
18+
<div
19+
class="css-1npfbn5"
20+
data-color-mode="dark"
21+
>
22+
<markdown-preview
23+
source="test"
24+
/>
25+
</div>
26+
</div>
27+
`;
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
.markdown {
2+
width: 100%;
3+
padding: 2rem;
4+
margin: 0.5rem 0;
5+
border-radius: 6px;
6+
font-size: 1rem;
7+
color: #fffffff0;
8+
background-color: transparent;
9+
line-height: 1.5;
10+
}
11+
12+
.markdown a {
13+
color: #ffffffa0;
14+
text-decoration: none;
15+
font-weight: 600;
16+
}
17+
18+
.markdown h3 {
19+
cursor: pointer;
20+
font-size: 1.2rem;
21+
font-weight: 500;
22+
color: #ffffffa0;
23+
}
24+
25+
.markdown h2 {
26+
cursor: pointer;
27+
font-size: 1.6rem;
28+
font-weight: 700;
29+
margin-top: 2rem;
30+
color: #fffffff0;
31+
}
32+
33+
.markdown h1 {
34+
display: none;
35+
}
36+
37+
.markdown div ul {
38+
background-color: light-dark(#ddffaa, #39422c);
39+
box-shadow:
40+
0 0 0 1px #ffffffc0,
41+
0 0 0 0 transparent;
42+
margin: 1rem;
43+
padding: 1rem;
44+
border: 1px solid #39422c;
45+
border-radius: 1rem;
46+
}
47+
48+
.markdown div ol {
49+
width: '100vw';
50+
background-color: light-dark(#ddffaa, #39422c);
51+
box-shadow:
52+
0 0 0 1px #ffffffc0,
53+
0 0 0 0 transparent;
54+
margin: 1rem;
55+
padding: 1rem;
56+
border: 1px solid #39422c;
57+
border-radius: 1rem;
58+
}
59+
60+
.markdown table {
61+
width: 'fit-content';
62+
border-collapse: collapse;
63+
border-spacing: 0;
64+
margin: 1rem;
65+
padding: 1rem;
66+
border: 1px solid #39422c;
67+
border-radius: 1rem;
68+
}
69+
70+
.markdown pre {
71+
background-color: #ffffff20;
72+
box-shadow:
73+
0 0 0 1px #ffffffc0,
74+
0 0 0 0 transparent;
75+
width: auto;
76+
padding: 2rem;
77+
padding-top: 1rem;
78+
padding-bottom: 1rem;
79+
}
80+
81+
.markdown pre code {
82+
content: 'light only';
83+
background-color: transparent;
84+
box-shadow: 0 0 0 0 transparent;
85+
padding: 0.25rem;
86+
z-index: 0;
87+
}
88+
89+
.markdown code {
90+
content: 'light only';
91+
background-color: #ffffff90;
92+
padding: 0.25rem;
93+
z-index: 0;
94+
}
95+
96+
.markdown li {
97+
list-style: disc;
98+
}
99+
100+
@media screen and (max-width: 1021px) {
101+
.markdown {
102+
column-count: 1;
103+
column-gap: 0rem;
104+
padding: 1rem;
105+
}
106+
107+
.markdown a {
108+
font-weight: 500;
109+
}
110+
111+
.markdown h3 {
112+
cursor: pointer;
113+
font-size: 1.2rem;
114+
font-weight: 500;
115+
margin: 0;
116+
}
117+
118+
.markdown h2 {
119+
cursor: pointer;
120+
font-size: 1.4rem;
121+
font-weight: 700;
122+
margin-top: 2rem;
123+
margin: 0;
124+
}
125+
126+
.markdown div ul {
127+
margin: 0.5rem;
128+
padding: 1rem;
129+
}
130+
131+
@media screen and (max-width: 1021px) {
132+
.markdown {
133+
width: 100%;
134+
column-count: 1;
135+
column-gap: 0rem;
136+
padding: 1rem;
137+
margin: 0.5rem 0;
138+
}
139+
140+
.markdown a {
141+
font-weight: 400;
142+
font-size: medium;
143+
}
144+
145+
.markdown h3 {
146+
font-size: 1.3rem;
147+
font-weight: 500;
148+
margin: 0;
149+
}
150+
151+
.markdown h2 {
152+
font-size: 1.5rem;
153+
font-weight: 700;
154+
margin-top: 2rem;
155+
margin: 0;
156+
}
157+
}
158+
.markdown div ul {
159+
margin: 0.6rem;
160+
padding: 0.7rem;
161+
font-size: medium;
162+
}
163+
}
164+
165+
@media screen and (max-width: 640px) {
166+
.markdown {
167+
width: 100%;
168+
padding: 1rem;
169+
margin: 0.5rem 0;
170+
}
171+
172+
.markdown a {
173+
font-weight: 300;
174+
font-size: small;
175+
}
176+
177+
.markdown h3 {
178+
font-size: 1rem;
179+
font-weight: 400;
180+
}
181+
182+
.markdown h2 {
183+
font-size: 1rem;
184+
font-weight: 700;
185+
}
186+
187+
.markdown div ul {
188+
margin: 0.5rem;
189+
padding: 0.5rem;
190+
font-size: small;
191+
}
192+
}

src/components/MdPreview/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { default as MdPreview } from './MdPreview';
2+
export { getMdFileDataInString } from './utils';
3+
export * from './types';

src/components/MdPreview/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type MdPreviewProps = { mdString: string };

src/components/MdPreview/utils.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { isEmpty } from 'lodash';
2+
3+
/**
4+
* Function to fetch the markdown string data from the path.
5+
* @param path Path of the markdown file.
6+
* @param responseHandler Function to handle the response.
7+
* @returns
8+
*/
9+
export const getMdFileDataInString = (
10+
path: string,
11+
responseHandler: (dataString: string) => void,
12+
) => {
13+
if (isEmpty(path)) return;
14+
15+
// Fetch the markdown file data.
16+
import(`../../${path}.md`)
17+
.then((res) => {
18+
fetch(res.default)
19+
.then((res) => {
20+
return res.text();
21+
})
22+
.then((res: string) => {
23+
responseHandler(res);
24+
})
25+
// eslint-disable-next-line no-console
26+
.catch((error) => console.log(error));
27+
})
28+
// eslint-disable-next-line no-console
29+
.catch((error) => console.log(error));
30+
};

0 commit comments

Comments
 (0)