From 06b8657a9a701d6b23e09a0b6ea0068173b307f0 Mon Sep 17 00:00:00 2001 From: Shawky Ebrahim Ahmed <101745968+shawkyebrahim2514@users.noreply.github.com> Date: Wed, 11 Dec 2024 12:57:48 +0200 Subject: [PATCH 1/2] Solving browser warnings and refactoring some codes --- react-frontend/package-lock.json | 137 ------------------ react-frontend/package.json | 2 - .../src/components/Button/index.tsx | 5 +- .../HTMLMarkdown/BlockquoteMarkdown.tsx | 57 ++++---- .../components/HTMLMarkdown/SpanMarkdown.tsx | 121 +++++++--------- .../customPlugins/customBlockquote.ts | 17 +-- .../src/components/HTMLMarkdown/index.tsx | 11 +- 7 files changed, 97 insertions(+), 253 deletions(-) diff --git a/react-frontend/package-lock.json b/react-frontend/package-lock.json index ea7ee11..82202f1 100644 --- a/react-frontend/package-lock.json +++ b/react-frontend/package-lock.json @@ -31,8 +31,6 @@ "react-spring": "^9.7.4", "rehype-stringify": "^10.0.1", "remark-breaks": "^4.0.0", - "remark-directive": "^3.0.0", - "remark-directive-rehype": "^0.4.2", "remark-gfm": "^4.0.0", "unist-util-visit": "^5.0.0", "uuid": "^11.0.2", @@ -10140,31 +10138,6 @@ "node": ">= 0.4" } }, - "node_modules/hast-util-parse-selector": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", - "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", - "dependencies": { - "@types/hast": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-parse-selector/node_modules/@types/hast": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", - "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/hast-util-parse-selector/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" - }, "node_modules/hast-util-to-html": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.3.tgz", @@ -10225,35 +10198,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hastscript": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", - "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", - "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^3.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hastscript/node_modules/@types/hast": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", - "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/hastscript/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" - }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -13807,25 +13751,6 @@ "css-mediaquery": "^0.1.2" } }, - "node_modules/mdast-util-directive": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", - "integrity": "sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/mdast-util-find-and-replace": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", @@ -14779,24 +14704,6 @@ "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-extension-directive": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", - "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "parse-entities": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/micromark-extension-gfm": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", @@ -18667,33 +18574,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/remark-directive": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.0.tgz", - "integrity": "sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-directive": "^3.0.0", - "micromark-extension-directive": "^3.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-directive-rehype": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/remark-directive-rehype/-/remark-directive-rehype-0.4.2.tgz", - "integrity": "sha512-T6e+IG+BwqU4++MK54vFb+KDFjs3a+tHeK6E0T0ctR1FSyngolfDtAEzqxHWlRzQZqGi2sB4DFXry6oqH87D/g==", - "dependencies": { - "hastscript": "^7.0.2", - "unist-util-map": "^3.1.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, "node_modules/remark-gfm": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", @@ -20984,23 +20864,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-map": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/unist-util-map/-/unist-util-map-3.1.3.tgz", - "integrity": "sha512-4/mDauoxqZ6geK97lJ6n2kDk6JK88Vh+hWMSJqyaaP/7eqN1dDhjcjnNxKNm3YU6Sw7PVJtcFMUbnmHvYzb6Vg==", - "dependencies": { - "@types/unist": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-map/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" - }, "node_modules/unist-util-position": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", diff --git a/react-frontend/package.json b/react-frontend/package.json index 841a9d2..7b2a0f3 100644 --- a/react-frontend/package.json +++ b/react-frontend/package.json @@ -26,8 +26,6 @@ "react-spring": "^9.7.4", "rehype-stringify": "^10.0.1", "remark-breaks": "^4.0.0", - "remark-directive": "^3.0.0", - "remark-directive-rehype": "^0.4.2", "remark-gfm": "^4.0.0", "unist-util-visit": "^5.0.0", "uuid": "^11.0.2", diff --git a/react-frontend/src/components/Button/index.tsx b/react-frontend/src/components/Button/index.tsx index f25fa74..3287257 100644 --- a/react-frontend/src/components/Button/index.tsx +++ b/react-frontend/src/components/Button/index.tsx @@ -32,6 +32,7 @@ type ButtonProps = { export default function Button({ icon, text, onClick, size = "lg", style, pointer, children }: ButtonProps) { const { theme } = useThemeContext(); const buttonStyle = useMemo(() => css({ + display: "inline-block", padding: differentSizes[size].padding, fontSize: differentSizes[size].fontSize, cursor: pointer ? "pointer" : "default", @@ -45,13 +46,13 @@ export default function Button({ icon, text, onClick, size = "lg", style, pointe }, [onClick]); return ( -
{icon} {text} {children} -
+ ) } diff --git a/react-frontend/src/components/HTMLMarkdown/BlockquoteMarkdown.tsx b/react-frontend/src/components/HTMLMarkdown/BlockquoteMarkdown.tsx index e798e48..2f91dec 100644 --- a/react-frontend/src/components/HTMLMarkdown/BlockquoteMarkdown.tsx +++ b/react-frontend/src/components/HTMLMarkdown/BlockquoteMarkdown.tsx @@ -5,6 +5,7 @@ import MainSection from '../MainSection'; import { toJsxRuntime } from 'hast-util-to-jsx-runtime' import { Fragment, jsx, jsxs } from 'react/jsx-runtime' import { markdownComponents } from '.'; +import { v4 as uuid } from 'uuid'; type BlockquoteElementType = "highlight-background" | "without-background"; type BlockquoteColorType = "base" | "secondary"; @@ -19,14 +20,17 @@ type BlockquoteMarkdownProps = { const BlockquoteMarkdown = ({ node, className, ...props }: BlockquoteMarkdownProps) => { const { theme } = useThemeContext(); - const contentJSXElementsFromAST = useMemo(() => ( - node?.children.map((element) => toJsxRuntime(element as RootContent, { + const contentJSXElementsFromAST = useMemo(() => { + let content = node?.children.map((element) => toJsxRuntime(element as RootContent, { Fragment, jsx, jsxs, passNode: true, components: { ...markdownComponents, br: () => null, - } - })) - ), [node?.children]); + }, + })); + return content?.map((element) => ( + {element} + )); + }, [node?.children]); const targetElement = useMemo((): TargetElementType => ({ "highlight-background": { @@ -64,27 +68,28 @@ const BlockquoteMarkdown = ({ node, className, ...props }: BlockquoteMarkdownPro ); } - return (
} - className='blockquote' - style={{ - ...props.style, - padding: "0 1rem", - position: "relative", - margin: "1rem 0", - backgroundColor: `${colors.containerBackgroundColor}`, - color: `${colors.barColor}` - }}> -
- {contentJSXElementsFromAST} -
); + return ( +
} + style={{ + ...props.style, + padding: "0 1rem", + position: "relative", + margin: "1rem 0", + backgroundColor: `${colors.containerBackgroundColor}`, + color: `${colors.barColor}` + }}> +
+ {contentJSXElementsFromAST} +
+ ); } export default BlockquoteMarkdown \ No newline at end of file diff --git a/react-frontend/src/components/HTMLMarkdown/SpanMarkdown.tsx b/react-frontend/src/components/HTMLMarkdown/SpanMarkdown.tsx index 541a533..d3e44d9 100644 --- a/react-frontend/src/components/HTMLMarkdown/SpanMarkdown.tsx +++ b/react-frontend/src/components/HTMLMarkdown/SpanMarkdown.tsx @@ -5,10 +5,12 @@ import { Fragment, jsx, jsxs } from 'react/jsx-runtime' import { markdownComponents } from '.'; import { toJsxRuntime } from 'hast-util-to-jsx-runtime' import Button from '../Button'; +import { v4 as uuid } from 'uuid'; + type SpanElementType = "highlight-area" | "highlight-text"; type SpanColorType = "base" | "secondary"; -type TargetElementType = Record { style: CSSProperties, children: React.ReactNode }>>; +type TargetElementType = Record>; type SpanMarkdownProps = { node?: Element, @@ -16,81 +18,43 @@ type SpanMarkdownProps = { const SpanMarkdown = ({ node, className, ...props }: SpanMarkdownProps) => { const { theme } = useThemeContext(); - let classes = (() => className?.split(' ') || [])(); - let content = node?.children; - - const contentJSXElementsFromAST = useMemo(() => ( - typeof content === 'string' ? content : - node?.children.map((element) => toJsxRuntime(element as RootContent, { - Fragment, jsx, jsxs, passNode: true, components: { - ...markdownComponents, - br: () => null, - } - })) - ), [content, node?.children]); - - const textStyle = useMemo((): CSSProperties => { - return { - position: "relative", - zIndex: 2, - } - }, []); - + const classes = useMemo(() => className?.split(" ") ?? [], [className]); + const contentJSXElementsFromAST = useMemo(() => { + let content = node?.children; + if (typeof content === 'string') return content; + let result = node?.children.map((element) => toJsxRuntime(element as RootContent, { + Fragment, jsx, jsxs, passNode: true, components: { + ...markdownComponents, + br: () => null, + }, + })); + return result?.map((element) => ( + {element} + )); + }, [node?.children]); const targetElement = useMemo((): TargetElementType => ({ "highlight-area": { - "base": (oldStyle: CSSProperties, children: React.ReactNode) => { - const spanStyle = { - ...oldStyle, - ...textStyle, - fontWeight: 600, - color: theme.colors.base[800], - background: `linear-gradient(to bottom, transparent 60%, ${theme.colors.base[200]} 60%)`, - } - return { - style: spanStyle, - children: children - } + "base": { + fontWeight: 600, + color: theme.colors.base[800], + background: `linear-gradient(to bottom, transparent 60%, ${theme.colors.base[200]} 60%)`, }, - "secondary": (oldStyle: CSSProperties, children: React.ReactNode) => { - const spanStyle = { - ...oldStyle, - ...textStyle, - fontWeight: 600, - color: theme.colors.base[800], - background: `linear-gradient(to bottom, transparent 60%, ${theme.colors.secondary[300]} 60%)` - } - return { - style: spanStyle, - children: children - } + "secondary": { + fontWeight: 600, + color: theme.colors.base[800], + background: `linear-gradient(to bottom, transparent 60%, ${theme.colors.secondary[300]} 60%)` }, }, "highlight-text": { - "base": (oldStyle: CSSProperties, children: React.ReactNode) => { - const spanStyle = { - ...oldStyle, - ...textStyle, - fontWeight: 600, - } - return { - style: spanStyle, - children: children - } + "base": { + fontWeight: 600, }, - "secondary": (oldStyle: CSSProperties, children: React.ReactNode) => { - const spanStyle = { - ...oldStyle, - ...textStyle, - color: theme.colors.secondary[500], - fontWeight: 600, - } - return { - style: spanStyle, - children: children - } + "secondary": { + color: theme.colors.secondary[500], + fontWeight: 600, }, }, - }), [textStyle, theme.colors.base, theme.colors.secondary]); + }), [theme.colors.base, theme.colors.secondary]); const spanElement = useMemo((): SpanElementType => { return classes.includes("highlight-area") ? "highlight-area" : "highlight-text"; }, [classes]); @@ -98,14 +62,27 @@ const SpanMarkdown = ({ node, className, ...props }: SpanMarkdownProps) => { return classes.includes("secondary") ? "secondary" : "base"; }, [classes]); const { style, children } = useMemo((): { style: CSSProperties, children: React.ReactNode } => { - return targetElement[spanElement][colorType](props.style ?? {}, contentJSXElementsFromAST); - }, [colorType, contentJSXElementsFromAST, props.style, spanElement, targetElement]); + return { + style: { + ...props.style, + ...targetElement[spanElement][colorType], + }, + children: contentJSXElementsFromAST + }; + }, [props.style, contentJSXElementsFromAST, targetElement, spanElement, colorType]); // `[[Button]]` if (classes.includes("button")) { - return + return ( + + ) } return ( diff --git a/react-frontend/src/components/HTMLMarkdown/customPlugins/customBlockquote.ts b/react-frontend/src/components/HTMLMarkdown/customPlugins/customBlockquote.ts index c82d0af..598aa2b 100644 --- a/react-frontend/src/components/HTMLMarkdown/customPlugins/customBlockquote.ts +++ b/react-frontend/src/components/HTMLMarkdown/customPlugins/customBlockquote.ts @@ -15,16 +15,15 @@ export const customBlockquote = () => { className: variation, } } + // If no title text is provided + if(titleText === "") return null; + // Chnage the node (paragraph) type to heading + matchedNode.stack[matchedNode.stack.length - 2].type = "heading"; + matchedNode.stack[matchedNode.stack.length - 2].depth = 5; return { - type: 'heading', - depth: 5, - children: [ - { - type: 'text', - value: titleText - } - ], - } as any; + type: 'text', + value: titleText + }; } ]) }) diff --git a/react-frontend/src/components/HTMLMarkdown/index.tsx b/react-frontend/src/components/HTMLMarkdown/index.tsx index af295c9..9fbcf3f 100644 --- a/react-frontend/src/components/HTMLMarkdown/index.tsx +++ b/react-frontend/src/components/HTMLMarkdown/index.tsx @@ -36,16 +36,17 @@ function HTMLMarkdown({ markdown }: Props) { return ( + components={markdownComponents} + > {markdown} ) From 73389cd11e7ff6f6748245a2a45bc3f412b3b1c9 Mon Sep 17 00:00:00 2001 From: Shawky Ebrahim Ahmed <101745968+shawkyebrahim2514@users.noreply.github.com> Date: Wed, 11 Dec 2024 13:23:34 +0200 Subject: [PATCH 2/2] Doing more refactoring --- .../HTMLMarkdown/customPlugins/customImage.ts | 2 +- .../customPlugins/customText/captureNewline.ts | 2 +- .../components/HTMLMarkdown/customPlugins/index.ts | 2 +- react-frontend/src/components/HTMLMarkdown/index.tsx | 12 ++++-------- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/react-frontend/src/components/HTMLMarkdown/customPlugins/customImage.ts b/react-frontend/src/components/HTMLMarkdown/customPlugins/customImage.ts index 0faa2d8..1b80fb9 100644 --- a/react-frontend/src/components/HTMLMarkdown/customPlugins/customImage.ts +++ b/react-frontend/src/components/HTMLMarkdown/customPlugins/customImage.ts @@ -47,7 +47,7 @@ const imageContainerStyle = (align: string): React.CSSProperties => { } } -export const customImagePlugin = () => { +export const customImage = () => { return function (tree: Nodes) { visit(tree, 'paragraph', (node: Nodes) => { let nodeFullText = toString(node); diff --git a/react-frontend/src/components/HTMLMarkdown/customPlugins/customText/captureNewline.ts b/react-frontend/src/components/HTMLMarkdown/customPlugins/customText/captureNewline.ts index 4fc6492..f63951f 100644 --- a/react-frontend/src/components/HTMLMarkdown/customPlugins/customText/captureNewline.ts +++ b/react-frontend/src/components/HTMLMarkdown/customPlugins/customText/captureNewline.ts @@ -9,7 +9,7 @@ export const captureNewline = (node: Node): customType => ({ children: [], data: { hProperties: { - style: "margin: 0.5rem 0; display: block;" + style: "margin: 0.5rem 0; display: grid;" } } } as any) diff --git a/react-frontend/src/components/HTMLMarkdown/customPlugins/index.ts b/react-frontend/src/components/HTMLMarkdown/customPlugins/index.ts index 6803683..975f8bd 100644 --- a/react-frontend/src/components/HTMLMarkdown/customPlugins/index.ts +++ b/react-frontend/src/components/HTMLMarkdown/customPlugins/index.ts @@ -1,4 +1,4 @@ export { customText } from './customText'; export { customBlockquote } from './customBlockquote'; export { customHighlightText } from './customHighlightText'; -export { customImagePlugin } from './customImage'; \ No newline at end of file +export { customImage } from './customImage'; \ No newline at end of file diff --git a/react-frontend/src/components/HTMLMarkdown/index.tsx b/react-frontend/src/components/HTMLMarkdown/index.tsx index 9fbcf3f..a16cdde 100644 --- a/react-frontend/src/components/HTMLMarkdown/index.tsx +++ b/react-frontend/src/components/HTMLMarkdown/index.tsx @@ -1,8 +1,6 @@ import ReactMarkdown, { Components } from 'react-markdown'; import remarkGfm from 'remark-gfm'; import remarkBreaks from 'remark-breaks' -import remarkDirective from 'remark-directive' -import remarkDirectiveRehype from 'remark-directive-rehype' import HrMarkdown from './HrMarkdown'; import UlMarkdown from './UlMarkdown'; import LiMarkdown from './LiMarkdown'; @@ -10,7 +8,7 @@ import HeadingMarkdown from './HeadingMarkdown'; import SpanMarkdown from './SpanMarkdown'; import BlockquoteMarkdown from './BlockquoteMarkdown'; import AncherLinkMarkdown from './AncherLinkMarkdown'; -import { customBlockquote, customHighlightText, customImagePlugin, customText } from './customPlugins'; +import { customBlockquote, customHighlightText, customImage, customText } from './customPlugins'; type Props = { readonly markdown: string @@ -36,11 +34,9 @@ function HTMLMarkdown({ markdown }: Props) { return (