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
onclickand other event handlers - Strips
<script>tags - Validates URLs in
hrefandsrcattributes - 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
- Start local server in project root
- Open
examples/directory in browser (if examples exist) - Or create
test.htmlwith 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-pagesbranch or enable in repository settings - Include
dist/wysihtml5.min.jsin 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
classesobject 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
documentmode 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
});