← Back to xing/wysihtml5

How to Deploy & Use xing/wysihtml5

wysihtml5 Deployment & Usage Guide

Prerequisites

  • Runtime: Modern web browser (IE 8+, Firefox, Chrome, Safari)
  • Dependencies: Rangy library (required for selection management)
  • Build Tools (optional): Node.js and npm if building from source
  • Server: Static web server (Apache, Nginx, or any static host) for deployment

Installation

1. Clone Repository

git clone https://github.com/tiff/wysihtml5.git
cd wysihtml5

2. Include Required Files

Add to your HTML <head>:

<!-- 1. Rangy library (required dependency) -->
<script src="path/to/rangy-core.js"></script>

<!-- 2. wysihtml5 library -->
<script src="dist/wysihtml5-0.3.0.min.js"></script>

<!-- 3. Parser rules (choose one) -->
<script src="parser_rules/advanced.js"></script>
<!-- OR -->
<script src="parser_rules/simple.js"></script>

3. Markup Structure

Create a textarea with toolbar:

<div id="toolbar" style="display: none;">
  <a data-wysihtml5-command="bold">Bold</a>
  <a data-wysihtml5-command="italic">Italic</a>
  <a data-wysihtml5-command="createLink">Link</a>
</div>

<textarea id="wysihtml5-textarea" placeholder="Enter text..."></textarea>

Configuration

Basic Initialization

var editor = new wysihtml5.Editor("wysihtml5-textarea", {
  toolbar:      "toolbar",
  parserRules:  wysihtml5ParserRules,  // Defined in parser_rules/advanced.js
  stylesheets:  ["path/to/editor.css"]
});

Parser Rules Configuration

Create custom parser rules in parser_rules/advanced.js or your own file:

var wysihtml5ParserRules = {
  // Allowed CSS classes
  classes: {
    "wysiwyg-color-red": 1,
    "wysiwyg-color-blue": 1,
    "wysiwyg-float-left": 1,
    "wysiwyg-float-right": 1
  },
  
  // Allowed tags and attributes
  tags: {
    p: {
      rename_tag: "p",
      set_class: "wysiwyg-paragraph"
    },
    br: {
      add_class: "wysiwyg-clear-both"
    },
    script: undefined,  // Removes script tags
    div: true,          // Keeps divs as-is
    a: {
      check_attributes: {
        href: "url"     // Validates URLs
      },
      set_attributes: {
        target: "_blank",
        rel: "nofollow"
      }
    },
    img: {
      check_attributes: {
        src: "url",
        alt: "alt"
      },
      rename_tag: "img"
    }
  }
};

Security Configuration

The HTML sanitizer (src/dom/parse.js) automatically:

  • Removes onclick and other event handlers
  • Strips <script> tags
  • Validates URLs in href and src attributes
  • Converts invalid tags to <span> elements

Configure strictness via parser rules:

// Strict mode - only allow specific classes
classes: {
  "wysiwyg-*": 1  // Allow all wysiwyg- prefixed classes
}

// Remove all inline styles
styles: {}  // Empty object removes all styles

Build & Run

Development Setup

If building from source (requires Node.js):

# Install dependencies (if package.json exists)
npm install

# Build distribution files
make build
# OR
npm run build

Direct Usage (No Build)

For immediate use without building:

# Simply serve the directory
python -m http.server 8000
# OR
npx serve .

Local Testing

  1. Start local server in project root
  2. Open examples/ directory in browser (if examples exist)
  3. Or create test.html with basic initialization code

Deployment

Static Hosting

Since wysihtml5 is a client-side library, deploy with your application:

Netlify:

# Build your app that includes wysihtml5
npm run build
# Deploy dist folder
netlify deploy --prod --dir=dist

Vercel:

vercel --prod

GitHub Pages:

  • Push to gh-pages branch or enable in repository settings
  • Include dist/wysihtml5.min.js in your committed files

CDN Usage

For production without self-hosting:

<!-- Use jsDelivr or unpkg -->
<script src="https://cdn.jsdelivr.net/npm/wysihtml5@0.3.0/dist/wysihtml5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/wysihtml5@0.3.0/parser_rules/advanced.js"></script>

Integration with Frameworks

React:

import { useEffect, useRef } from 'react';

function WysiEditor() {
  const textareaRef = useRef(null);
  
  useEffect(() => {
    if (textareaRef.current) {
      const editor = new wysihtml5.Editor(textareaRef.current, {
        toolbar: 'toolbar',
        parserRules: wysihtml5ParserRules
      });
      return () => editor.destroy();
    }
  }, []);
  
  return (
    <>
      <div id="toolbar" style={{display: 'none'}}>
        <button data-wysihtml5-command="bold">Bold</button>
      </div>
      <textarea ref={textareaRef} />
    </>
  );
}

Troubleshooting

Editor Not Initializing

Issue: wysihtml5 is not defined

  • Solution: Ensure Rangy is loaded before wysihtml5:
<script src="rangy-core.js"></script>
<script src="wysihtml5.js"></script>

Issue: Toolbar buttons not working

  • Solution: Ensure toolbar element exists and is visible when initializing:
// Toolbar must be in DOM before initialization
document.getElementById('toolbar').style.display = 'block';
var editor = new wysihtml5.Editor('textarea', {
  toolbar: 'toolbar'
});

Content Sanitization Issues

Issue: HTML tags being stripped unexpectedly

  • Solution: Check parser rules in advanced.js. Tags not explicitly allowed are converted to <span>:
// Add to parserRules.tags to allow specific tag
tags: {
  customtag: true,  // Keep as-is
  script: undefined // Explicitly remove
}

Issue: Classes being removed from elements

  • Solution: Add allowed classes to classes object in parser rules:
classes: {
  "my-custom-class": 1,
  "another-class": 1
}

Browser Compatibility

Issue: Caret not visible in empty editor (Firefox)

  • Solution: The library includes a caret hack automatically. If issues persist, ensure CSS:
.wysihtml5-editor {
  min-height: 1em;
}

Issue: IE8/9 contentEditable problems

  • Solution: Ensure document mode is standards:
<meta http-equiv="X-UA-Compatible" content="IE=edge">

Security Warnings

Issue: onclick attributes being stripped

  • Solution: This is by design for XSS protection. Event handlers are removed by the HTML sanitizer in src/dom/parse.js. Use delegated event listeners instead:
// Instead of inline onclick
document.getElementById('editor').addEventListener('click', function(e) {
  // Handle clicks
});

Performance Issues

Issue: Slow parsing on large documents

  • Solution: Disable live parsing or debounce input:
var editor = new wysihtml5.Editor('textarea', {
  parserRules: wysihtml5ParserRules,
  // Use getValue(parse: true) only when saving, not on every change
});