Skip to content

Commit

Permalink
feat: extend markdown support
Browse files Browse the repository at this point in the history
  • Loading branch information
Pauline Didier committed Aug 9, 2024
1 parent 0bfba86 commit eb44a4e
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 87 deletions.
96 changes: 96 additions & 0 deletions app/src/components/model/panels/DescriptionPreview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { marked } from "marked";
import DOMPurify from "dompurify";
import Box from "@mui/material/Box";

marked.use({
extensions: [
{
name: "heading",
renderer({ text, depth }) {
return `<h${depth + 1}>${text}</h${depth + 1}>`;
},
},
{
name: "image",
renderer(_) {
return "Images are not supported";
},
},
{
name: "link",
renderer(token) {
if (!token.href) {
return `<p><strong>${token.text}</strong> (link without href)</p>`;
}
return `<a href="${token.href}" target="_blank" rel="noopener noreferrer">${token.text}</a>`;
},
},
{
name: "code",
renderer(token) {
if (!token.text) {
return "";
}
if (token.lang) {
return `<div><p>\`\`\`${token.lang}</p><pre style="margin-left:1em"><code class="language-${token.lang}">${token.text}</code></pre><p>\`\`\`</p></div>`;
}
return `<div><p>\`\`\`</p><pre style="margin-left:1em"><code class="language-${token.lang}">${token.text}</code></pre><p>\`\`\`</p></div>`;
},
},
{
name: "list",
renderer(token) {
const itemList = token.items.map((i) => {
return (
"<li style='margin-bottom:0'>" + i.raw.replace(/\n+$/, "") + "</li>"
);
});
if (token.ordered) {
return `<ol>${itemList.join("\n")}</ol>`;
} else {
return `<ul>${itemList.join("\n")}</ul>`;
}
},
},
],
});

const domPurityConfig = {
USE_PROFILES: { html: true },
FORBID_TAGS: ["img"],
ADD_ATTR: ["target"],
};

export const DescriptionPreview = ({
description,
readOnly,
showDescriptionTextField,
sx = {},
}) => {
if (!description) {
showDescriptionTextField(true);
return null;
}

const sanitizedHtml = DOMPurify.sanitize(
marked.parse(description),
domPurityConfig
);

if (readOnly) {
return (
<Box
dangerouslySetInnerHTML={{ __html: sanitizedHtml }}
sx={{ ...sx }}
></Box>
);
} else {
return (
<Box
dangerouslySetInnerHTML={{ __html: sanitizedHtml }}
sx={{ ...sx }}
onDoubleClick={showDescriptionTextField}
></Box>
);
}
};
16 changes: 9 additions & 7 deletions app/src/components/model/panels/left/ComponentTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ import { MultipleSystemsDropdown } from "../../../elements/MultipleSystemsDropdo
import { COMPONENT_TYPE } from "../../board/constants";
import { useSelectedComponent } from "../../hooks/useSelectedComponent";
import { TechStacksDropdown } from "./TechStackDropdown";
import { DescriptionPreview } from "./DescriptionPreview";
import { set } from "lodash";
import { DescriptionPreview } from "../DescriptionPreview";

export function ComponentTab() {
const dispatch = useDispatch();
Expand Down Expand Up @@ -214,11 +213,14 @@ export function ComponentTab() {
/>
)}
{(showDescriptionPreview || readOnly) && (
<DescriptionPreview
description={description}
showDescriptionTextField={showDescriptionTextField}
readOnly={readOnly}
/>
<>
<Typography variant="body1">Description</Typography>
<DescriptionPreview
description={description}
showDescriptionTextField={showDescriptionTextField}
readOnly={readOnly}
/>
</>
)}
</Box>
</CardContent>
Expand Down
63 changes: 0 additions & 63 deletions app/src/components/model/panels/left/DescriptionPreview.js

This file was deleted.

59 changes: 48 additions & 11 deletions app/src/components/model/panels/right/EditableTypography.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,48 @@
import { Input, Typography } from "@mui/material";
import { useEffect, useState } from "react";
import Box from "@mui/material/Box";
import { marked } from "marked";
import DOMPurify from "dompurify";
import { DescriptionPreview } from "../DescriptionPreview";

marked.use({
extensions: [
{
name: "heading",
renderer({ text, depth }) {
return `<h${depth + 1}>${text}</h${depth + 1}>`;
},
},
{
name: "image",
renderer(_) {
return "Images are not supported";
},
},
{
name: "link",
renderer(token) {
console.log({ token });
return `<a href="${token.href}" target="_blank" rel="noopener noreferrer">${token.text}</a>`;
},
},
{
name: "list",
renderer(token) {
const itemList = token.items.map((i) => {
return (
"<li style='margin-bottom:0'>" + i.raw.replace(/\n+$/, "") + "</li>"
);
});
if (token.ordered) {
return `<ol>${itemList.join("\n")}</ol>`;
} else {
return `<ul>${itemList.join("\n")}</ul>`;
}
},
},
],
});

export function EditableTypography({
text,
Expand Down Expand Up @@ -63,14 +106,8 @@ export function EditableTypography({
}}
/>
) : (
<Typography
variant={variant}
color={color}
onClick={() => {
if (!readOnly) {
setIsEditing(!isEditing);
}
}}
<DescriptionPreview
description={text}
sx={{
...sx,
wordBreak: "break-word",
Expand All @@ -80,9 +117,9 @@ export function EditableTypography({
},
}),
}}
>
{value || placeholder}
</Typography>
readOnly={readOnly}
showDescriptionTextField={() => setIsEditing(!isEditing)}
/>
)}
</>
);
Expand Down
69 changes: 63 additions & 6 deletions app/src/components/model/panels/right/Suggestion.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,65 @@ import {
} from "../../../../api/gram/suggestions";
import { useModelID } from "../../hooks/useModelID";
import { useSelectedComponent } from "../../hooks/useSelectedComponent";
import { marked } from "marked";
import DOMPurify from "dompurify";
import { DescriptionPreview } from "../DescriptionPreview";

function SuggestionDescription({ description }) {
marked.use({
extensions: [
{
name: "heading",
renderer({ text, depth }) {
return `<h${depth + 1}>${text}</h${depth + 1}>`;
},
},
{
name: "image",
renderer(_) {
return "Images are not supported";
},
},
{
name: "list",
renderer(token) {
const itemList = token.items.map((i) => {
return (
"<li style='margin-bottom:0'>" +
i.raw.replace(/\n+$/, "") +
"</li>"
);
});
if (token.ordered) {
return `<ol>${itemList.join("\n")}</ol>`;
} else {
return `<ul>${itemList.join("\n")}</ul>`;
}
},
},
],
});

const domPurityConfig = {
USE_PROFILES: { html: true },
FORBID_TAGS: ["img", "table", "tr", "td", "th"],
};

const sanitizedHtml = DOMPurify.sanitize(
marked.parse(description),
domPurityConfig
);

return (
<Box>
<Typography variant="caption" color="text.secondary">
Description:
</Typography>
<br />
<Typography variant="body2">{description}</Typography>
</Box>
);
}

function SuggestionMitigations({ suggestion, threatSuggestions }) {
const threatsMitigated = suggestion?.mitigates?.filter((m) =>
Expand Down Expand Up @@ -81,17 +140,15 @@ export function Suggestion({ suggestion, rejected, readOnly, isControl }) {
{suggestion.title}
</Typography>
{suggestion.description && (
<Typography
variant="body1"
color="text.secondary"
<DescriptionPreview
description={suggestion.description}
readOnly
sx={{
paddingBottom: "10px",
lineHeight: "1.45",
fontSize: "0.75rem",
}}
>
{suggestion.description}
</Typography>
/>
)}
<SuggestionMitigations
threatSuggestions={threatSuggestions}
Expand Down

0 comments on commit eb44a4e

Please sign in to comment.