2 * This is based loosely on tinymce
3 * @class Roo.htmleditor.TidyEntities
5 * https://github.com/thorn0/tinymce.html/blob/master/tinymce.html.js
8 Roo.htmleditor.TidyEntities = {
16 // Decodes text by using the browser
18 // Build a two way lookup table for the entities
20 // Unpack entities lookup where the numbers are in radix 32 to reduce the size
23 this.namedEntities = buildEntitiesLookup(this.namedEntitiesData, 32);
28 buildEntitiesLookup: function(items, radix) {
29 var i, chr, entity, lookup = {};
31 items = items.split(',');
33 // Build entities lookup table
34 for (i = 0; i < items.length; i += 2) {
35 chr = String.fromCharCode(parseInt(items[i], radix));
36 // Only add non base entities
37 if (!baseEntities[chr]) {
38 entity = '&' + items[i + 1] + ';';
80 // Needs to be escaped since the YUI compressor would otherwise break the code
87 // Reverse lookup table for raw entities
96 attrsCharsRegExp : /[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
97 textCharsRegExp : /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
98 rawCharsRegExp : /[<>&\"\']/g,
99 entityRegExp : /&#([a-z0-9]+);?|&([a-z0-9]+);/gi,
100 namedEntities : false,
101 namedEntitiesData : [
602 * Encodes the specified string using raw entities. This means only the required XML base entities will be encoded.
605 * @param {String} text Text to encode.
606 * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
607 * @return {String} Entity encoded text.
609 encodeRaw: function(text, attr)
612 return text.replace(attr ? this.attrsCharsRegExp : this.textCharsRegExp, function(chr) {
613 return t.baseEntities[chr] || chr;
617 * Encoded the specified text with both the attributes and text entities. This function will produce larger text contents
618 * since it doesn't know if the context is within a attribute or text node. This was added for compatibility
619 * and is exposed as the DOMUtils.encode function.
621 * @method encodeAllRaw
622 * @param {String} text Text to encode.
623 * @return {String} Entity encoded text.
625 encodeAllRaw: function(text) {
627 return ('' + text).replace(this.rawCharsRegExp, function(chr) {
628 return t.baseEntities[chr] || chr;
632 * Encodes the specified string using numeric entities. The core entities will be
633 * encoded as named ones but all non lower ascii characters will be encoded into numeric entities.
635 * @method encodeNumeric
636 * @param {String} text Text to encode.
637 * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
638 * @return {String} Entity encoded text.
640 encodeNumeric: function(text, attr) {
642 return text.replace(attr ? this.attrsCharsRegExp : this.textCharsRegExp, function(chr) {
643 // Multi byte sequence convert it to a single entity
644 if (chr.length > 1) {
645 return '&#' + (1024 * (chr.charCodeAt(0) - 55296) + (chr.charCodeAt(1) - 56320) + 65536) + ';';
647 return t.baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';';
651 * Encodes the specified string using named entities. The core entities will be encoded
652 * as named ones but all non lower ascii characters will be encoded into named entities.
654 * @method encodeNamed
655 * @param {String} text Text to encode.
656 * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
657 * @param {Object} entities Optional parameter with entities to use.
658 * @return {String} Entity encoded text.
660 encodeNamed: function(text, attr, entities) {
662 entities = entities || this.namedEntities;
663 return text.replace(attr ? this.attrsCharsRegExp : this.textCharsRegExp, function(chr) {
664 return t.baseEntities[chr] || entities[chr] || chr;
668 * Returns an encode function based on the name(s) and it's optional entities.
670 * @method getEncodeFunc
671 * @param {String} name Comma separated list of encoders for example named,numeric.
672 * @param {String} entities Optional parameter with entities to use instead of the built in set.
673 * @return {function} Encode function to be used.
675 getEncodeFunc: function(name, entities) {
676 entities = this.buildEntitiesLookup(entities) || this.namedEntities;
678 function encodeNamedAndNumeric(text, attr) {
679 return text.replace(attr ? t.attrsCharsRegExp : t.textCharsRegExp, function(chr) {
680 return t.baseEntities[chr] || entities[chr] || '&#' + chr.charCodeAt(0) + ';' || chr;
684 function encodeCustomNamed(text, attr) {
685 return t.encodeNamed(text, attr, entities);
687 // Replace + with , to be compatible with previous TinyMCE versions
688 name = this.makeMap(name.replace(/\+/g, ','));
689 // Named and numeric encoder
690 if (name.named && name.numeric) {
691 return this.encodeNamedAndNumeric;
697 return encodeCustomNamed;
699 return this.encodeNamed;
703 return this.encodeNumeric;
706 return this.encodeRaw;
709 * Decodes the specified string, this will replace entities with raw UTF characters.
712 * @param {String} text Text to entity decode.
713 * @return {String} Entity decoded string.
715 decode: function(text)
718 return text.replace(this.entityRegExp, function(all, numeric) {
720 numeric = 'x' === numeric.charAt(0).toLowerCase() ? parseInt(numeric.substr(1), 16) : parseInt(numeric, 10);
722 if (numeric > 65535) {
724 return String.fromCharCode(55296 + (numeric >> 10), 56320 + (1023 & numeric));
726 return t.asciiMap[numeric] || String.fromCharCode(numeric);
728 return t.reverseEntities[all] || t.namedEntities[all] || t.nativeDecode(all);
731 nativeDecode : function (text) {
734 makeMap : function (items, delim, map) {
737 delim = delim || ',';
738 if (typeof items == "string") {
739 items = items.split(delim);
751 Roo.htmleditor.TidyEntities.init();