Skip to content

Commit

Permalink
feat(mdx-editor): tweet embed previews (#1808)
Browse files Browse the repository at this point in the history
  • Loading branch information
ncarazon authored Dec 24, 2024
1 parent e119c6f commit 4f2dccb
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 5 deletions.
38 changes: 38 additions & 0 deletions front_end/package-lock.json

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

1 change: 1 addition & 0 deletions front_end/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"react-hook-form": "^7.52.1",
"react-hot-toast": "^2.4.1",
"react-merge-refs": "^2.1.1",
"react-tweet": "^3.2.1",
"remark": "^15.0.1",
"sass": "^1.77.6",
"sharp": "^0.33.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ const NotebookEditor: React.FC<NotebookEditorProps> = ({

{!isEditing && (
<div id={contentId}>
<MarkdownEditor mode="read" markdown={markdown} />
<MarkdownEditor mode="read" markdown={markdown} withTwitterPreview />
</div>
)}
</div>
Expand Down
1 change: 1 addition & 0 deletions front_end/src/components/comment_feed/comment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ const Comment: FC<CommentProps> = ({
)}
mode={"read"}
withUgcLinks
withTwitterPreview
/>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const TWITTER_REGEX =
/https?:\/\/(?:twitter|vxtwitter|x)\.com\/(?:#!\/)?\w+\/status(?:es)?\/(\d+)/g;

export const transformTwitterLinks = (markdown: string): string => {
const matches = markdown.match(TWITTER_REGEX);

if (!matches) {
return markdown;
}

const uniqueTweetIds = new Set<string>();
matches.forEach((match) => {
const tweetIdMatch = match.match(/(\d+)$/);
if (tweetIdMatch && tweetIdMatch[1]) {
uniqueTweetIds.add(tweetIdMatch[1]);
}
});

const tweetComponents = Array.from(uniqueTweetIds)
.map((id) => `<Tweet id="${id}" />`)
.join("\n");

return `${markdown}\n\n${tweetComponents}`;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { JsxComponentDescriptor } from "@mdxeditor/editor";
import { Tweet } from "react-tweet";

import createEditorComponent from "../createJsxComponent";

export const tweetDescriptor: JsxComponentDescriptor = {
name: "Tweet",
props: [{ name: "id", type: "string", required: true }],
kind: "text",
hasChildren: false,
Editor: createEditorComponent(Tweet),
};
8 changes: 7 additions & 1 deletion front_end/src/components/markdown_editor/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
revertMathJaxTransform,
transformMathJax,
} from "./embedded_math_jax/helpers";
import { transformTwitterLinks } from "./embedded_twitter/helpers";

// escape < and { that is not correctly used
function escapePlainTextSymbols(str: string) {
Expand Down Expand Up @@ -32,13 +33,18 @@ function formatBlockquoteNewlines(markdown: string): string {

export function processMarkdown(
markdown: string,
revert: boolean = false
config?: { revert?: boolean; withTwitterPreview?: boolean }
): string {
const { revert, withTwitterPreview } = config ?? {};

markdown = formatBlockquoteNewlines(markdown);
markdown = revert
? revertMathJaxTransform(markdown)
: transformMathJax(markdown);
markdown = escapePlainTextSymbols(markdown);
if (withTwitterPreview) {
markdown = transformTwitterLinks(markdown);
}

return markdown;
}
16 changes: 13 additions & 3 deletions front_end/src/components/markdown_editor/initialized_editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
embeddedQuestionDescriptor,
EmbedQuestionAction,
} from "@/components/markdown_editor/embedded_question";
import { tweetDescriptor } from "@/components/markdown_editor/embedded_twitter";
import { processMarkdown } from "@/components/markdown_editor/helpers";
import { linkPlugin } from "@/components/markdown_editor/plugins/link";
import { mentionsPlugin } from "@/components/markdown_editor/plugins/mentions";
Expand All @@ -63,6 +64,7 @@ type EditorMode = "write" | "read";
const jsxComponentDescriptors: JsxComponentDescriptor[] = [
mathJaxDescriptor,
embeddedQuestionDescriptor,
tweetDescriptor,
];

const PlainTextCodeEditorDescriptor: CodeBlockEditorDescriptor = {
Expand Down Expand Up @@ -90,6 +92,7 @@ export type MarkdownEditorProps = {
withUgcLinks?: boolean;
className?: string;
initialMention?: string;
withTwitterPreview?: boolean;
};

/**
Expand All @@ -110,6 +113,7 @@ const InitializedMarkdownEditor: FC<
shouldConfirmLeave = false,
withUgcLinks,
initialMention,
withTwitterPreview = false,
}) => {
const { user } = useAuth();
const { theme } = useAppTheme();
Expand All @@ -121,14 +125,20 @@ const InitializedMarkdownEditor: FC<

// Transform MathJax syntax to JSX embeds to properly utilise the MarkJax renderer
const formattedMarkdown = useMemo(
() => processMarkdown(markdown),
[markdown]
() =>
processMarkdown(markdown, {
revert: false,
withTwitterPreview: mode === "read" && withTwitterPreview,
}),
[markdown, mode, withTwitterPreview]
);

const handleEditorChange = useCallback(
(value: string) => {
// Revert the MathJax transformation before passing the markdown to the parent component
onChange?.(processMarkdown(value, true));
onChange?.(
processMarkdown(value, { revert: true, withTwitterPreview: false })
);
},
[onChange]
);
Expand Down

0 comments on commit 4f2dccb

Please sign in to comment.