CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-markdown-to-jsx

Convert markdown to JSX with ease for React and React-like projects.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

component-overrides.mddocs/

Component Overrides

Powerful system for replacing any HTML tag with custom React components, including props injection and component mapping.

Capabilities

Override System

Flexible mechanism to replace any HTML tag rendered by markdown with custom React components or modified props.

interface Override {
  /** React component to replace the default HTML tag */
  component?: React.ElementType;
  /** Props to inject into the rendered element */
  props?: object;
}

type Overrides = {
  /** Override any standard HTML tag */
  [tag in HTMLTags]?: Override | React.ElementType;
} & {
  /** Override custom components by name */
  [customComponent: string]: Override | React.ElementType;
};

type HTMLTags = keyof React.JSX.IntrinsicElements;

Usage Examples:

import Markdown from "markdown-to-jsx";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";

// Component replacement
const CustomLink = ({ href, children, ...props }) => (
  <a 
    href={href} 
    target="_blank" 
    rel="noopener noreferrer"
    className="external-link"
    {...props}
  >
    {children} 🔗
  </a>
);

// Props injection
const markdownOptions = {
  overrides: {
    // Replace component entirely
    a: CustomLink,
    
    // Component with props
    h1: { 
      component: "h2", 
      props: { className: "main-title" } 
    },
    
    // Props only (keeps original tag)
    p: { 
      props: { className: "paragraph" } 
    },
    
    // Code block with syntax highlighting
    code: {
      component: ({ className, children, ...props }) => {
        const lang = className?.replace('lang-', '') || 'text';
        return (
          <SyntaxHighlighter language={lang} {...props}>
            {children}
          </SyntaxHighlighter>
        );
      }
    }
  }
};

function App() {
  return (
    <Markdown options={markdownOptions}>
      # This becomes h2 with class "main-title"
      
      This paragraph gets the "paragraph" class.
      
      [This link](https://example.com) opens in new tab with icon.
      
      ```javascript
      // This code gets syntax highlighting
      const hello = "world";
      ```
    </Markdown>
  );
}

Component Replacement

Replace any HTML tag with a custom React component while preserving all functionality.

/**
 * Replace HTML tag with custom component
 * Component receives all standard HTML attributes plus children
 */
type ComponentOverride = React.ElementType;

// Usage in overrides
const overrides = {
  tagName: CustomComponent
};

Usage Examples:

// Custom heading component
const CustomHeading = ({ level, id, children, ...props }) => {
  const Tag = `h${level}`;
  return (
    <Tag 
      id={id}
      className={`heading-${level}`}
      {...props}
    >
      <span className="heading-icon">#</span>
      {children}
    </Tag>
  );
};

// Custom image component with lazy loading
const LazyImage = ({ src, alt, title, ...props }) => {
  return (
    <img
      src={src}
      alt={alt}
      title={title}
      loading="lazy"
      className="responsive-image"
      {...props}
    />
  );
};

// Custom list component
const CustomList = ({ ordered, start, children, ...props }) => {
  const Tag = ordered ? "ol" : "ul";
  return (
    <Tag 
      start={start}
      className={`list ${ordered ? 'ordered' : 'unordered'}`}
      {...props}
    >
      {children}
    </Tag>
  );
};

const options = {
  overrides: {
    h1: CustomHeading,
    h2: CustomHeading,
    h3: CustomHeading,
    img: LazyImage,
    ul: CustomList,
    ol: CustomList
  }
};

Props Injection

Add or modify props for HTML elements without changing the component type.

/**
 * Props injection configuration
 * Props are merged with existing attributes, with override props taking precedence
 */
interface PropsOverride {
  props: object;
  component?: React.ElementType; // Optional component replacement
}

Usage Examples:

const options = {
  overrides: {
    // Add classes to all paragraphs
    p: { 
      props: { className: "prose-paragraph" } 
    },
    
    // Style all blockquotes
    blockquote: { 
      props: { 
        className: "quote",
        style: { 
          borderLeft: "4px solid #ccc",
          paddingLeft: "1rem",
          fontStyle: "italic"
        }
      } 
    },
    
    // Make all tables responsive
    table: { 
      props: { 
        className: "table-responsive",
        style: { width: "100%" }
      } 
    },
    
    // Add target to all links
    a: { 
      props: { 
        target: "_blank",
        rel: "noopener noreferrer"
      } 
    }
  }
};

// Markdown content
const content = `
# Title

This is a paragraph that will get the "prose-paragraph" class.

> This blockquote gets custom styling.

| Col 1 | Col 2 |
|-------|-------|
| A     | B     |

[This link](https://example.com) opens in new tab.
`;

Class Name Merging

Override props are intelligently merged with existing attributes, with special handling for className.

// Built-in classes are preserved and merged
const options = {
  overrides: {
    code: { 
      props: { className: "custom-code" } 
    }
  }
};

// Fenced code block with language
const markdown = `
\`\`\`javascript
const code = "example";
\`\`\`
`;

// Results in: <code className="lang-javascript custom-code">

Advanced Override Patterns

Complex override scenarios for sophisticated component replacement and prop manipulation.

Usage Examples:

// Conditional component based on props
const SmartImage = ({ alt, src, ...props }) => {
  const isExternal = src.startsWith('http');
  
  if (isExternal) {
    return (
      <figure className="external-image">
        <img src={src} alt={alt} {...props} />
        <figcaption>External: {alt}</figcaption>
      </figure>
    );
  }
  
  return <img src={src} alt={alt} {...props} />;
};

// Dynamic component based on content
const SmartCode = ({ className, children, ...props }) => {
  const language = className?.replace('lang-', '');
  
  // Inline code
  if (!language) {
    return <code className="inline-code" {...props}>{children}</code>;
  }
  
  // Block code with syntax highlighting
  return (
    <SyntaxHighlighter 
      language={language}
      className="code-block"
      {...props}
    >
      {children}
    </SyntaxHighlighter>
  );
};

// Wrapper component that adds functionality
const InteractiveHeading = ({ children, id, ...props }) => {
  const handleClick = () => {
    navigator.clipboard.writeText(`#${id}`);
  };
  
  return (
    <h2 id={id} onClick={handleClick} className="interactive-heading" {...props}>
      {children}
      <button className="copy-link" aria-label="Copy link">🔗</button>
    </h2>
  );
};

const advancedOptions = {
  overrides: {
    img: SmartImage,
    code: SmartCode,
    h2: InteractiveHeading
  }
};

Override Validation

TypeScript provides compile-time validation for override configurations to prevent common mistakes.

const options = {
  overrides: {
    // ✅ Valid - React component
    p: CustomParagraph,
    
    // ✅ Valid - HTML tag string
    h1: "h2",
    
    // ✅ Valid - Override object
    a: { 
      component: CustomLink,
      props: { className: "link" }
    },
    
    // ❌ TypeScript error - invalid override
    span: { invalidProp: true },
    
    // ❌ TypeScript error - not a valid HTML tag
    invalidTag: CustomComponent
  }
};

docs

advanced-configuration.md

component-interface.md

component-overrides.md

core-compilation.md

custom-rendering.md

index.md

utility-functions.md

tile.json