@unizap/html-editor
v0.2.0
Published
A TipTap-based rich HTML paste/edit component with style-preserving paste and code output view.
Maintainers
Readme
@unizap/html-editor
A rich HTML paste/edit component built on TipTap, designed to preserve formatting exactly as it's copied from external sources (Google Docs, Word, web pages, etc.) while giving you clean, sanitized HTML output.
Features
- Style-preserving paste — retains inline styles, block-level formatting, and images from pasted content instead of stripping it down to plain text.
- Sanitized input — pasted HTML is sanitized via DOMPurify before it reaches the editor.
- Built-in toolbar — headings, text alignment, tables, links, images, and more, out of the box.
- Code output view — a syntax-highlighted (via Shiki), copyable, optionally prettified view of the editor's HTML output.
- Fully typed — ships with TypeScript declarations.
Install
npm install @unizap/html-editorPeer dependencies
This package expects react and react-dom (v18+) to already be installed in your project.
Usage
Import the component and its stylesheet, then wire it up as a controlled input. By default the editor grows with its content (starting at a min-height, no forced height):
"use client";
import { useState } from "react";
import { HtmlEditor, CodeOutput } from "@unizap/html-editor";
import "@unizap/html-editor/styles.css";
export default function Example() {
const [html, setHtml] = useState("");
return (
<div className="mx-auto flex max-w-4xl flex-col gap-4 p-4">
<HtmlEditor value={html} onChange={setHtml} placeholder="Paste or type..." />
<CodeOutput code={html} />
</div>
);
}To instead place the editor in a bounded flex layout (fixed height, independently scrollable — e.g. a two-pane dashboard), pass contentClassName:
<div className="flex h-screen gap-4 p-4">
<HtmlEditor
value={html}
onChange={setHtml}
className="flex min-h-0 flex-1 flex-col"
contentClassName="flex min-h-0 flex-1 flex-col"
/>
<CodeOutput code={html} className="min-h-0 flex-1" />
</div>Note:
HtmlEditorandCodeOutputare client components — use them inside a component marked"use client"(or import them from one) if you're using React Server Components / Next.js App Router.
API
<HtmlEditor />
| Prop | Type | Required | Description |
| ------------------ | ------------------------ | -------- | --------------------------------------------------------- |
| value | string | Yes | The current HTML content, as an HTML string. |
| onChange | (html: string) => void | Yes | Called with the updated HTML string on every edit. |
| placeholder | string | No | Placeholder text shown when the editor is empty. Defaults to "Paste or type...". |
| className | string | No | Class applied to the editor's outer wrapping element. |
| contentClassName | string | No | Class applied to the scrollable editor content area. Pass a bounded-flex className (e.g. "flex min-h-0 flex-1 flex-col") to make the editor fill and scroll within a fixed-height layout; omit it to let the editor grow with its content. |
The editor also shows a dashed-border "dropzone" hint when it's empty and unfocused.
<CodeOutput />
| Prop | Type | Required | Description |
| ----------- | -------- | -------- | ----------------------------------------------------- |
| code | string | Yes | The HTML string to render, highlight, and make copyable. |
| className | string | No | Class applied to the output panel's wrapping element. |
Includes a "Prettify" toggle and a "Copy" button in its header bar.
Other exports
For advanced use cases, the underlying TipTap extensions and utilities used by HtmlEditor are also exported:
Toolbar— the formatting toolbar used internally byHtmlEditor.PreserveStyle,PreserveStyleBlock,PreserveStyleSpan— TipTap extensions that retain inline/block styles on pasted content.PreservedImage— a TipTap image extension configured to allow base64 image data.sanitizePastedHtml(html: string): string— sanitizes raw pasted HTML using DOMPurify.prettifyHtml(html: string): string— formats/indents an HTML string for readability.
License
MIT
