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 🙏

© 2026 – Pkg Stats / Ryan Hefner

canva-editor-html

v1.0.2

Published

A full-page HTML editor component for React with iframe isolation

Readme

canva-editor

A full-page HTML editor component for React that allows users to edit text content within complete HTML documents while preserving structure, styles, and scripts.

Features

  • ✅ Edit text content directly in the preview
  • ✅ Preserves HTML structure, styles, and scripts
  • ✅ Download edited HTML with proper Doctype
  • ✅ Load external HTML files
  • ✅ Real-time editing with contentEditable
  • ✅ Isolated iframe prevents CSS/JS conflicts
  • ✅ TypeScript support
  • ✅ Responsive design

Architecture

This component follows robust architectural decisions:

  1. Iframe Isolation - Uses <iframe> to create a separate browsing context
  2. Content Injection - Uses document.write() for same-origin content injection
  3. ContentEditable Engine - Makes the entire <body> editable
  4. Proper Serialization - Preserves Doctype when saving
  5. Security Sandbox - Controlled iframe permissions
  6. UX Enhancements - Injected CSS for better editing experience

Installation

npm install canva-editor

or

yarn add canva-editor

Quick Start

import HTMLEditor from 'canva-editor';
import 'canva-editor/dist/style.css';

function App() {
    const htmlContent = `<!DOCTYPE html>
<html lang="en">
<head>
    <title>My Page</title>
    <style>
        body { font-family: Arial; padding: 20px; }
        h1 { color: #333; }
    </style>
</head>
<body>
    <h1>Hello World</h1>
    <p>Click to edit this text!</p>
</body>
</html>`;

    return (
        <div style={{ height: '100vh' }}>
            <HTMLEditor
                initialHTML={htmlContent}
                fileName="my-document.html"
            />
        </div>
    );
}

export default App;

Component Usage

Basic Usage

import HTMLEditor from './HTMLEditor';

function App() {
    const htmlContent = `<!DOCTYPE html>
<html lang="en">
<head>
    <title>My Page</title>
</head>
<body>
    <h1>Hello World</h1>
</body>
</html>`;

    return (
        <HTMLEditor
            initialHTML={htmlContent}
            fileName="my-document.html"
        />
    );
}

Advanced Usage with Callbacks

import HTMLEditor from './HTMLEditor';

function App() {
    const handleSave = (htmlContent) => {
        console.log('Saved HTML:', htmlContent);
        // Send to server, save to database, etc.
    };

    const handleChange = (htmlContent) => {
        console.log('Content changed');
        // Auto-save, track changes, etc.
    };

    return (
        <HTMLEditor
            initialHTML={htmlContent}
            fileName="document.html"
            onSave={handleSave}
            onChange={handleChange}
            showToolbar={true}
        />
    );
}

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | initialHTML | string | '' | Initial HTML content to load | | fileName | string | 'document.html' | Default file name for downloads | | onSave | function | null | Callback when content is saved (receives HTML string) | | onChange | function | null | Callback when content changes (receives HTML string) | | showToolbar | boolean | true | Whether to show the toolbar |

Features

  • ✅ Edit text content directly in the preview
  • ✅ Preserves HTML structure, styles, and scripts
  • ✅ Download edited HTML with proper Doctype
  • ✅ Load external HTML files
  • ✅ Reset to original content
  • ✅ Real-time editing with contentEditable
  • ✅ Isolated iframe prevents CSS/JS conflicts
  • ✅ Responsive design

File Structure

.
├── HTMLEditor.jsx          # Main component
├── HTMLEditor.css          # Component styles
├── App.jsx                 # Example usage
├── App.css                 # App styles
├── main.jsx                # React entry point
├── index.html              # HTML template
├── package.json            # Dependencies
├── vite.config.js          # Vite configuration
├── sample.html             # Sample HTML to edit
└── reasoning.txt           # Architecture documentation

How It Works

1. Iframe Isolation

The component uses an <iframe> to create a completely separate browsing context. This prevents:

  • CSS from the editor bleeding into the loaded HTML
  • JavaScript conflicts between the editor and loaded content

2. Content Injection

Uses document.write() to inject HTML content synchronously while maintaining same-origin status, allowing the React app to read/write the iframe content.

3. Editable Content

Makes the iframe's <body> element contentEditable, allowing users to click anywhere and edit text while preserving the HTML structure.

4. Saving

Manually reconstructs the complete HTML document including the Doctype using XMLSerializer and outerHTML.

5. Security

Uses iframe sandbox attribute with controlled permissions:

  • allow-same-origin - Allows React to access iframe content
  • allow-scripts - Allows scripts in the HTML to run
  • allow-forms - Allows form submission
  • allow-popups - Allows opening new windows

Customization

Custom Styling

You can customize the editor appearance by modifying HTMLEditor.css or overriding the CSS classes:

.html-editor-container { /* Main container */ }
.html-editor-header { /* Toolbar */ }
.html-editor-btn-primary { /* Primary buttons */ }
.html-editor-iframe { /* Editor iframe */ }

Hide Toolbar

<HTMLEditor
    initialHTML={htmlContent}
    showToolbar={false}
/>

Programmatic Access

You can access the current HTML programmatically:

const iframeRef = useRef();

// Access via ref
const currentHTML = iframeRef.current?.getHTML();

Browser Support

  • Chrome/Edge (latest)
  • Firefox (latest)
  • Safari (latest)

Security Considerations

⚠️ Important: This editor uses allow-same-origin in the iframe sandbox, which means malicious HTML could potentially access your app's cookies and localStorage. Only use this with trusted HTML content or implement additional security measures.

Development

Local Development

Clone the repository and install dependencies:

git clone https://github.com/yourusername/canva-editor.git
cd canva-editor
npm install

Run the development server:

npm run dev

Building the Library

Build the library for distribution:

npm run build:lib

This creates the dist/ folder with:

  • canva-editor.es.js - ES module
  • canva-editor.umd.js - UMD module
  • style.css - Component styles
  • Source maps

Publishing to npm

  1. Update the version in package.json:
npm version patch  # or minor, or major
  1. Build the library:
npm run build:lib
  1. Login to npm (if not already logged in):
npm login
  1. Publish:
npm publish

The prepublishOnly script will automatically build the library before publishing.

Project Structure

.
├── src/
│   ├── HTMLEditor.jsx       # Main component
│   ├── HTMLEditor.css        # Component styles
│   ├── index.js              # Entry point
│   └── index.d.ts            # TypeScript definitions
├── dist/                     # Built library (generated)
├── App.jsx                   # Demo app
├── package.json
├── vite.config.lib.js        # Vite config for library build
├── README.md
└── LICENSE

License

MIT

Contributing

Feel free to submit issues and pull requests!