parkhojeong commented on code in PR #66809:
URL: https://github.com/apache/airflow/pull/66809#discussion_r3239003324


##########
airflow-core/src/airflow/ui/package.json:
##########


Review Comment:
   Should we update the third-party license notices for the new bundled UI 
dependencies added in this PR?
   
    For reference, `airflow-core/LICENSE` already lists bundled UI dependencies 
such as Chakra UI and hue, with their corresponding license texts under 
`airflow-core/3rd-party-licenses/`.



##########
airflow-core/src/airflow/ui/src/components/ReactMarkdown.tsx:
##########


Review Comment:
   Is the new behavior intended for every ReactMarkdown usage, or only for Dag 
Documentation?
   
    This component is shared by Dag/Task docs, dashboard alerts, action note 
previews, Trigger Dag / FlexibleForm descriptions, and editable markdown 
previews. 



##########
airflow-core/src/airflow/ui/src/components/ReactMarkdown.tsx:
##########
@@ -106,81 +122,107 @@ const UlComponent = ({ children }: PropsWithChildren) => 
(
   </List.Root>
 );
 
-// Factory function for the code component that needs style
-const createCodeComponent =
-  (style: typeof oneDark | typeof oneLight) =>
-  ({
-    children,
-    className,
-    inline,
-  }: {
-    readonly children: ReactNode;
-    readonly className?: string;
-    readonly inline?: boolean;
-  }) => {
-    if (inline) {
-      return (
-        <Code display="inline" p={2}>
-          {children}
-        </Code>
-      );
+type CodeElementProps = {
+  readonly children?: ReactNode;
+  readonly className?: string;
+};
+
+type MermaidDiagramProps = {
+  readonly chart: string;
+  readonly theme: "dark" | "default";
+};
+
+type MarkdownRendererProps = {
+  readonly mermaidTheme: MermaidDiagramProps["theme"];
+  readonly style: SyntaxTheme;
+};
+
+const extractTextContent = (children: CodeElementProps["children"]): string => 
{
+  if (typeof children === "number" || typeof children === "string") {
+    return String(children);
+  }
+
+  if (Array.isArray(children)) {
+    return children
+      .map((child) => (typeof child === "number" || typeof child === "string" 
? String(child) : ""))
+      .join("");
+  }
+
+  return "";
+};
+
+const CodeComponent = ({ children }: PropsWithChildren) => <Code 
display="inline">{children}</Code>;
+
+// Factory function for the pre component that needs style
+const createPreComponent =
+  (style: SyntaxTheme, mermaidTheme: MermaidDiagramProps["theme"]) =>
+  ({ children }: { readonly children?: ReactNode }) => {
+    const [codeElement] = Children.toArray(children);
+
+    if (!isValidElement<CodeElementProps>(codeElement)) {
+      return <Box my={3}>{children}</Box>;
     }
 
     // Extract language from className (format: "language-python")
-    const match = /language-(?<lang>\w+)/u.exec(className ?? "");
+    const { children: codeChildren, className } = codeElement.props;
+    const match = /language-(?<lang>[-\w]+)/u.exec(className ?? "");
     const language = match?.groups?.lang;
+    const childString = extractTextContent(codeChildren).replace(/\n$/u, "");
 
-    // Safely extract string content from children
-    let childString = "";
-
-    if (typeof children === "string") {
-      childString = children;
-    } else if (Array.isArray(children)) {
-      childString = children.filter((child) => typeof child === 
"string").join("");
+    if (language === "mermaid") {
+      return <MarkdownMermaid chart={childString} fallbackStyle={style} 
theme={mermaidTheme} />;
     }
 
-    return (
-      <SyntaxHighlighter language={language ?? "text"} PreTag="div" 
style={style} wrapLongLines>
-        {childString.replace(/\n$/u, "")}
-      </SyntaxHighlighter>
-    );
+    return <MarkdownCodeBlock language={language} style={style} 
value={childString} />;
   };
 
+const createMarkdownComponents = ({ mermaidTheme, style }: 
MarkdownRendererProps): Components => ({
+  // eslint-disable-next-line id-length
+  a: LinkComponent,
+  blockquote: BlockquoteComponent,
+  code: CodeComponent,
+  del: DelComponent,
+  em: EmComponent,
+  h1: makeHeading("h1"),
+  h2: makeHeading("h2"),
+  h3: makeHeading("h3"),
+  h4: makeHeading("h4"),
+  h5: makeHeading("h5"),
+  h6: makeHeading("h6"),
+  hr: HrComponent,
+  img: ImgComponent,
+  li: LiComponent,
+  ol: OlComponent,
+  // eslint-disable-next-line id-length
+  p: PComponent,
+  pre: createPreComponent(style, mermaidTheme),
+  table: TableComponent,
+  tbody: Table.Body,
+  td: Table.Cell,
+  text: TextComponent,
+  th: Table.ColumnHeader,
+  thead: Table.Header,
+  tr: Table.Row,
+  ul: UlComponent,
+});
+
 const ReactMarkdown = (props: Options) => {
   const { colorMode } = useColorMode();
   const style = colorMode === "dark" ? oneDark : oneLight;
-
-  const components = {
-    // eslint-disable-next-line id-length
-    a: LinkComponent,
-    blockquote: BlockquoteComponent,
-    code: createCodeComponent(style),
-    del: DelComponent,
-    em: EmComponent,
-    h1: makeHeading("h1"),
-    h2: makeHeading("h2"),
-    h3: makeHeading("h3"),
-    h4: makeHeading("h4"),
-    h5: makeHeading("h5"),
-    h6: makeHeading("h6"),
-    hr: HrComponent,
-    img: ImgComponent,
-    li: LiComponent,
-    ol: OlComponent,
-    // eslint-disable-next-line id-length
-    p: PComponent,
-    pre: PreComponent,
-    table: TableComponent,
-    tbody: Table.Body,
-    td: Table.Cell,
-    text: TextComponent,
-    th: Table.ColumnHeader,
-    thead: Table.Header,
-    tr: Table.Row,
-    ul: UlComponent,
-  };
-
-  return <ReactMD components={components as Components} {...props} 
remarkPlugins={[remarkGfm]} skipHtml />;
+  const mermaidTheme = colorMode === "dark" ? "dark" : "default";
+  const components = createMarkdownComponents({ mermaidTheme, style });
+
+  return (
+    <Box alignSelf="stretch" css={markdownContentStyles} maxWidth="100%" 
minWidth={0} width="100%">
+      <ReactMD
+        components={components}
+        {...props}
+        rehypePlugins={[rehypeKatex]}
+        remarkPlugins={[remarkGfm, remarkMath]}

Review Comment:
   This enables remarkMath with its default `singleDollarTextMath: true`, which 
changes how ordinary dollar text is parsed across all ReactMarkdown usages. For 
example, `Costs $5 and $10 today.` is parsed as inline math (`5 and `), so the 
dollar amounts render incorrectly.
   
   <img width="700" height="438" alt="Image" 
src="https://github.com/user-attachments/assets/75c5c57d-442b-4b62-82e4-c51baece7837";
 />
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to