Skip to content

The rendered Markdown has too much spaces in tailwind + nextjs project #905

@SinoAHpx

Description

@SinoAHpx

Initial checklist

Affected package

"tailwindcss": "^4.0.17" "react-markdown": "^10.1.0"

Steps to reproduce

Here is a component:

import { memo } from 'react';
import type { FC } from 'react';
import ReactMarkdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import remarkGfm from 'remark-gfm';
import { cn } from '@/lib/utils';

type MessageFormatterProps = {
  content: string;
  className?: string;
};

/**
 * MessageFormatter renders chat content with Markdown and code syntax highlighting
 * 
 * Features:
 * - Renders markdown with GitHub Flavored Markdown support
 * - Syntax highlighting for code blocks with language detection
 * - Styled inline code and text formatting
 * - Responsive layout with proper spacing
 */
const MessageFormatter: FC<MessageFormatterProps> = ({ content, className }) => {
  // Custom rendering components for markdown elements
  const markdownComponents = {
    // Code block handling with syntax highlighting
    code({ className, children, ...props }: any) {
      // Extract language from className (format: language-xxx)
      const match = /language-(\w+)/.exec(className || '');
      const language = match ? match[1] : '';

      // Determine if we're dealing with a code block or inline code
      const isCodeBlock = props.node?.position?.start.line !== props.node?.position?.end.line;

      return isCodeBlock ? (
        <SyntaxHighlighter
          language={language || 'text'}
          style={atomDark}
          PreTag="div"
          customStyle={{
            borderRadius: '6px',
            marginTop: '0.3em',
            marginBottom: '0.3em',
            fontSize: '0.9em',
          }}
        >
          {String(children).replace(/\n$/, '')}
        </SyntaxHighlighter>
      ) : (
        <code className="bg-muted px-1 py-0.5 rounded text-xs">
          {children}
        </code>
      );
    },
    // Heading components with minimal margins
    h1: ({ children }: any) => (
      <h1 className="text-xl font-bold">{children}</h1>
    ),
    h2: ({ children }: any) => (
      <h2 className="text-lg font-bold">{children}</h2>
    ),
    h3: ({ children }: any) => (
      <h3 className="text-base font-bold">{children}</h3>
    ),
    h4: ({ children }: any) => (
      <h4 className="font-bold">{children}</h4>
    ),
    // Link styling
    a: ({ children, href }: any) => (
      <a
        href={href}
        target="_blank"
        rel="noopener noreferrer"
        className="text-primary underline hover:text-primary/80"
      >
        {children}
      </a>
    ),
    // List elements
    ul: ({ children }: any) => <ul className="list-item ml-0 mr-0 mt-0 mb-0 ">{children}</ul>,
    ol: ({ children }: any) => <ol className="list-decimal pl-2 my-0.5">{children}</ol>,
    li: ({ children }: any) => <li className="my-0 mt-0 mb-0">{children}</li>,
    // Paragraph
    p: ({ children }: any) => <p className="my-0.5 mt-0 mb-0">{children}</p>,
    // Tables
    table: ({ children }: any) => (
      <div className="my-0.5 overflow-x-auto">
        <table className="min-w-[50%] border-collapse text-xs">{children}</table>
      </div>
    ),
    thead: ({ children }: any) => <thead className="bg-muted/50">{children}</thead>,
    tr: ({ children }: any) => <tr className="border-b border-border">{children}</tr>,
    th: ({ children }: any) => <th className="px-2 py-1 text-left font-medium">{children}</th>,
    td: ({ children }: any) => <td className="px-2 py-1 border-r last:border-r-0 border-border">{children}</td>,
    // Blockquote
    blockquote: ({ children }: any) => (
      <blockquote className="border-l-2 border-border pl-2 italic my-1 text-muted-foreground">
        {children}
      </blockquote>
    ),
    // Horizontal rule
    hr: () => <hr className="my-1 border-t border-border" />,
  };

  return (
    <div className={cn("max-w-none", className)}>
      <ReactMarkdown
        remarkPlugins={[remarkGfm]}
        components={markdownComponents}
      >
        {content}
      </ReactMarkdown>
    </div>
  );
};

export default memo(MessageFormatter);

Actual behavior

This is actual rendered:

Image

Expected behavior

This is the exact text from previous image, but pasted in Obsidian:

Image

Runtime

No response

Package manager

bun

Operating system

macOS Sequoia 15.3.2

Build and bundle tools

Next.js

Metadata

Metadata

Assignees

No one assigned

    Labels

    👎 phase/noPost cannot or will not be acted on🙋 no/questionThis does not need any changes

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions