npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

rehype-custom-component

v1.1.1

Published

Rehype plugin to transform custom components into to handle with React

Readme

rehype-custom-component

npm license bundle size

A modern rehype plugin to transform custom component shortcodes with XML attributes into HTML elements for React integration.

Installation

npm install rehype-custom-component
# or
yarn add rehype-custom-component
# or
pnpm add rehype-custom-component

Usage

This plugin transforms <CustomComponent> shortcodes with standard XML/HTML attributes into custom HTML elements that can be handled by React or other frameworks.

Basic Usage

import { unified } from 'unified';
import rehypeParse from 'rehype-parse';
import rehypeStringify from 'rehype-stringify';
import rehypeCustomComponent from 'rehype-custom-component';

const processor = unified()
  .use(rehypeParse)
  .use(rehypeCustomComponent)
  .use(rehypeStringify);

const input = `<p>Check out this component: <CustomComponent name="button" type="primary" /></p>`;
const result = await processor.process(input);
console.log(String(result));
// Output: <p>Check out this component: <custom-component name="button" type="primary"></custom-component></p>

With Markdown

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeCustomComponent from 'rehype-custom-component';
import rehypeStringify from 'rehype-stringify';

const processor = unified()
  .use(remarkParse)
  .use(remarkRehype)
  .use(rehypeCustomComponent)
  .use(rehypeStringify);

const markdown = `# My Page

Here's a custom component: <CustomComponent name="card" title="Hello" theme="dark" />`;

const result = await processor.process(markdown);

Shortcode Format

The plugin recognizes shortcodes with standard XML/HTML attribute syntax:

<CustomComponent name="componentName" attr1="value1" attr2="value2" />

Supported Attribute Formats

<!-- Quoted values -->
<CustomComponent name="button" type="primary" />

<!-- Unquoted values -->
<CustomComponent name="icon" size=large />

<!-- Boolean attributes (flags) -->
<CustomComponent name="input" required disabled />

<!-- Mixed attributes -->
<CustomComponent name="card" title="Hello" active priority=high />

Multi-line Support

The plugin supports multi-line shortcodes with flexible formatting:

<!-- Standard multi-line -->
<CustomComponent 
  name="complexComponent" 
  title="My Title"
  theme="dark"
  size="large"
/>

<!-- Minimal multi-line -->
<CustomComponent
  data="value"
  />

Examples

<!-- Simple component -->
<CustomComponent name="button" type="primary" />
→ <custom-component name="button" type="primary"></custom-component>

<!-- Complex component with multiple attributes -->
<CustomComponent name="card" title="Hello" author="John" published />
→ <custom-component name="card" title="Hello" author="John" published></custom-component>

<!-- Component without additional attributes -->
<CustomComponent name="simple" />
→ <custom-component name="simple"></custom-component>

<!-- Component with boolean flags -->
<CustomComponent name="input" required disabled />
→ <custom-component name="input" required disabled></custom-component>

Options

tagName

  • Type: string
  • Default: 'custom-component'

The HTML tag name to use for the generated elements.

.use(rehypeCustomComponent, { tagName: 'my-component' })

// <CustomComponent name="button" type="primary" />
// → <my-component name="button" type="primary"></my-component>

matchName

  • Type: string
  • Default: 'CustomComponent'

The component name to match in the source text.

.use(rehypeCustomComponent, { matchName: 'MyComponent' })

// <MyComponent name="button" type="primary" />
// → <custom-component name="button" type="primary"></custom-component>

TypeScript

This package includes TypeScript declarations and supports both CommonJS and ES modules.

import rehypeCustomComponent, { CustomComponentOptions } from 'rehype-custom-component';

const options: CustomComponentOptions = {
  tagName: 'my-component'
};

React Integration

The generated HTML elements can be easily handled in React:

// Create a custom component handler
const CustomComponentRenderer = ({ name, ...props }) => {
  switch (name) {
    case 'button':
      return <Button {...props} />;
    case 'card':
      return <Card {...props} />;
    case 'icon':
      return <Icon {...props} />;
    default:
      return <div data-unknown-component={name} {...props} />;
  }
};

// Register in your MDX or HTML processor
const components = {
  'custom-component': CustomComponentRenderer,
  // other components...
};

// Usage example with the generated attributes
// <CustomComponent name="button" type="primary" size="large" disabled />
// becomes:
// <Button type="primary" size="large" disabled />

Advanced Usage

Custom Component Names

You can configure the plugin to match different component names:

// Match React-style components
.use(rehypeCustomComponent, { 
  matchName: 'ReactComponent',
  tagName: 'react-component' 
})

// Match Vue-style components
.use(rehypeCustomComponent, { 
  matchName: 'VueComponent',
  tagName: 'vue-component' 
})

Processing Pipeline

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeCustomComponent from 'rehype-custom-component';
import rehypeStringify from 'rehype-stringify';

const processor = unified()
  .use(remarkParse)
  .use(remarkRehype, { allowDangerousHtml: true })
  .use(rehypeCustomComponent, {
    tagName: 'my-component',
    matchName: 'Component'
  })
  .use(rehypeStringify, { allowDangerousHtml: true });

const markdown = `
# My Document

<Component name="hero" title="Welcome" subtitle="Get started" primary />

Regular markdown content continues here.
`;

const result = await processor.process(markdown);

Requirements

  • Node.js 16 or higher
  • Modern ES6+ environment supporting matchAll(), nullish coalescing (??), and spread syntax

Features

  • Modern ES6+ implementation with array destructuring and functional programming patterns
  • XML/HTML attribute syntax - familiar and standard
  • Multi-line component support with flexible formatting
  • Boolean attributes for flags and toggles
  • Quoted and unquoted values support
  • Configurable component names and output tag names
  • TypeScript support with full type definitions
  • Zero dependencies except for peer dependencies

License

MIT © Matthieu Conti

Contributing

Issues and pull requests are welcome! Please check the existing issues before creating a new one.

Related