374564ea049283d91fe7cfbed352d65bda515902
[roojs1] / Roo / htmleditor / TidyEntities.js
1 /***
2  * This is based loosely on tinymce 
3  * @class Roo.htmleditor.TidyEntities
4  * @static
5  * https://github.com/thorn0/tinymce.html/blob/master/tinymce.html.js
6  */
7
8 Roo.htmleditor.TidyEntities = {
9     
10     /**
11      * initialize data..
12      */
13     init : function (){
14     
15         
16        // Decodes text by using the browser
17        
18        // Build a two way lookup table for the entities
19        
20        // Unpack entities lookup where the numbers are in radix 32 to reduce the size
21        
22       
23        this.namedEntities = buildEntitiesLookup(this.namedEntitiesData, 32);
24        
25     },
26
27
28      buildEntitiesLookup: function(items, radix) {
29         var i, chr, entity, lookup = {};
30         if (items) {
31             items = items.split(',');
32             radix = radix || 10;
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] + ';';
39                     lookup[chr] = entity;
40                     lookup[entity] = chr;
41                 }
42             }
43             return lookup;
44         }
45         return {};
46     },
47     
48     asciiMap : {
49             128: '€',
50             130: '‚',
51             131: 'ƒ',
52             132: '„',
53             133: '…',
54             134: '†',
55             135: '‡',
56             136: 'ˆ',
57             137: '‰',
58             138: 'Š',
59             139: '‹',
60             140: 'Œ',
61             142: 'Ž',
62             145: '‘',
63             146: '’',
64             147: '“',
65             148: '”',
66             149: '•',
67             150: '–',
68             151: '—',
69             152: '˜',
70             153: '™',
71             154: 'š',
72             155: '›',
73             156: 'œ',
74             158: 'ž',
75             159: 'Ÿ'
76     },
77     // Raw entities
78     baseEntities : {
79         '"': '&quot;',
80         // Needs to be escaped since the YUI compressor would otherwise break the code
81         '\'': '&#39;',
82         '<': '&lt;',
83         '>': '&gt;',
84         '&': '&amp;',
85         '`': '&#96;'
86     },
87     // Reverse lookup table for raw entities
88     reverseEntities : {
89         '&lt;': '<',
90         '&gt;': '>',
91         '&amp;': '&',
92         '&quot;': '"',
93         '&apos;': '\''
94     },
95     
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 : [ 
102         '50',
103         'nbsp',
104         '51',
105         'iexcl',
106         '52',
107         'cent',
108         '53',
109         'pound',
110         '54',
111         'curren',
112         '55',
113         'yen',
114         '56',
115         'brvbar',
116         '57',
117         'sect',
118         '58',
119         'uml',
120         '59',
121         'copy',
122         '5a',
123         'ordf',
124         '5b',
125         'laquo',
126         '5c',
127         'not',
128         '5d',
129         'shy',
130         '5e',
131         'reg',
132         '5f',
133         'macr',
134         '5g',
135         'deg',
136         '5h',
137         'plusmn',
138         '5i',
139         'sup2',
140         '5j',
141         'sup3',
142         '5k',
143         'acute',
144         '5l',
145         'micro',
146         '5m',
147         'para',
148         '5n',
149         'middot',
150         '5o',
151         'cedil',
152         '5p',
153         'sup1',
154         '5q',
155         'ordm',
156         '5r',
157         'raquo',
158         '5s',
159         'frac14',
160         '5t',
161         'frac12',
162         '5u',
163         'frac34',
164         '5v',
165         'iquest',
166         '60',
167         'Agrave',
168         '61',
169         'Aacute',
170         '62',
171         'Acirc',
172         '63',
173         'Atilde',
174         '64',
175         'Auml',
176         '65',
177         'Aring',
178         '66',
179         'AElig',
180         '67',
181         'Ccedil',
182         '68',
183         'Egrave',
184         '69',
185         'Eacute',
186         '6a',
187         'Ecirc',
188         '6b',
189         'Euml',
190         '6c',
191         'Igrave',
192         '6d',
193         'Iacute',
194         '6e',
195         'Icirc',
196         '6f',
197         'Iuml',
198         '6g',
199         'ETH',
200         '6h',
201         'Ntilde',
202         '6i',
203         'Ograve',
204         '6j',
205         'Oacute',
206         '6k',
207         'Ocirc',
208         '6l',
209         'Otilde',
210         '6m',
211         'Ouml',
212         '6n',
213         'times',
214         '6o',
215         'Oslash',
216         '6p',
217         'Ugrave',
218         '6q',
219         'Uacute',
220         '6r',
221         'Ucirc',
222         '6s',
223         'Uuml',
224         '6t',
225         'Yacute',
226         '6u',
227         'THORN',
228         '6v',
229         'szlig',
230         '70',
231         'agrave',
232         '71',
233         'aacute',
234         '72',
235         'acirc',
236         '73',
237         'atilde',
238         '74',
239         'auml',
240         '75',
241         'aring',
242         '76',
243         'aelig',
244         '77',
245         'ccedil',
246         '78',
247         'egrave',
248         '79',
249         'eacute',
250         '7a',
251         'ecirc',
252         '7b',
253         'euml',
254         '7c',
255         'igrave',
256         '7d',
257         'iacute',
258         '7e',
259         'icirc',
260         '7f',
261         'iuml',
262         '7g',
263         'eth',
264         '7h',
265         'ntilde',
266         '7i',
267         'ograve',
268         '7j',
269         'oacute',
270         '7k',
271         'ocirc',
272         '7l',
273         'otilde',
274         '7m',
275         'ouml',
276         '7n',
277         'divide',
278         '7o',
279         'oslash',
280         '7p',
281         'ugrave',
282         '7q',
283         'uacute',
284         '7r',
285         'ucirc',
286         '7s',
287         'uuml',
288         '7t',
289         'yacute',
290         '7u',
291         'thorn',
292         '7v',
293         'yuml',
294         'ci',
295         'fnof',
296         'sh',
297         'Alpha',
298         'si',
299         'Beta',
300         'sj',
301         'Gamma',
302         'sk',
303         'Delta',
304         'sl',
305         'Epsilon',
306         'sm',
307         'Zeta',
308         'sn',
309         'Eta',
310         'so',
311         'Theta',
312         'sp',
313         'Iota',
314         'sq',
315         'Kappa',
316         'sr',
317         'Lambda',
318         'ss',
319         'Mu',
320         'st',
321         'Nu',
322         'su',
323         'Xi',
324         'sv',
325         'Omicron',
326         't0',
327         'Pi',
328         't1',
329         'Rho',
330         't3',
331         'Sigma',
332         't4',
333         'Tau',
334         't5',
335         'Upsilon',
336         't6',
337         'Phi',
338         't7',
339         'Chi',
340         't8',
341         'Psi',
342         't9',
343         'Omega',
344         'th',
345         'alpha',
346         'ti',
347         'beta',
348         'tj',
349         'gamma',
350         'tk',
351         'delta',
352         'tl',
353         'epsilon',
354         'tm',
355         'zeta',
356         'tn',
357         'eta',
358         'to',
359         'theta',
360         'tp',
361         'iota',
362         'tq',
363         'kappa',
364         'tr',
365         'lambda',
366         'ts',
367         'mu',
368         'tt',
369         'nu',
370         'tu',
371         'xi',
372         'tv',
373         'omicron',
374         'u0',
375         'pi',
376         'u1',
377         'rho',
378         'u2',
379         'sigmaf',
380         'u3',
381         'sigma',
382         'u4',
383         'tau',
384         'u5',
385         'upsilon',
386         'u6',
387         'phi',
388         'u7',
389         'chi',
390         'u8',
391         'psi',
392         'u9',
393         'omega',
394         'uh',
395         'thetasym',
396         'ui',
397         'upsih',
398         'um',
399         'piv',
400         '812',
401         'bull',
402         '816',
403         'hellip',
404         '81i',
405         'prime',
406         '81j',
407         'Prime',
408         '81u',
409         'oline',
410         '824',
411         'frasl',
412         '88o',
413         'weierp',
414         '88h',
415         'image',
416         '88s',
417         'real',
418         '892',
419         'trade',
420         '89l',
421         'alefsym',
422         '8cg',
423         'larr',
424         '8ch',
425         'uarr',
426         '8ci',
427         'rarr',
428         '8cj',
429         'darr',
430         '8ck',
431         'harr',
432         '8dl',
433         'crarr',
434         '8eg',
435         'lArr',
436         '8eh',
437         'uArr',
438         '8ei',
439         'rArr',
440         '8ej',
441         'dArr',
442         '8ek',
443         'hArr',
444         '8g0',
445         'forall',
446         '8g2',
447         'part',
448         '8g3',
449         'exist',
450         '8g5',
451         'empty',
452         '8g7',
453         'nabla',
454         '8g8',
455         'isin',
456         '8g9',
457         'notin',
458         '8gb',
459         'ni',
460         '8gf',
461         'prod',
462         '8gh',
463         'sum',
464         '8gi',
465         'minus',
466         '8gn',
467         'lowast',
468         '8gq',
469         'radic',
470         '8gt',
471         'prop',
472         '8gu',
473         'infin',
474         '8h0',
475         'ang',
476         '8h7',
477         'and',
478         '8h8',
479         'or',
480         '8h9',
481         'cap',
482         '8ha',
483         'cup',
484         '8hb',
485         'int',
486         '8hk',
487         'there4',
488         '8hs',
489         'sim',
490         '8i5',
491         'cong',
492         '8i8',
493         'asymp',
494         '8j0',
495         'ne',
496         '8j1',
497         'equiv',
498         '8j4',
499         'le',
500         '8j5',
501         'ge',
502         '8k2',
503         'sub',
504         '8k3',
505         'sup',
506         '8k4',
507         'nsub',
508         '8k6',
509         'sube',
510         '8k7',
511         'supe',
512         '8kl',
513         'oplus',
514         '8kn',
515         'otimes',
516         '8l5',
517         'perp',
518         '8m5',
519         'sdot',
520         '8o8',
521         'lceil',
522         '8o9',
523         'rceil',
524         '8oa',
525         'lfloor',
526         '8ob',
527         'rfloor',
528         '8p9',
529         'lang',
530         '8pa',
531         'rang',
532         '9ea',
533         'loz',
534         '9j0',
535         'spades',
536         '9j3',
537         'clubs',
538         '9j5',
539         'hearts',
540         '9j6',
541         'diams',
542         'ai',
543         'OElig',
544         'aj',
545         'oelig',
546         'b0',
547         'Scaron',
548         'b1',
549         'scaron',
550         'bo',
551         'Yuml',
552         'm6',
553         'circ',
554         'ms',
555         'tilde',
556         '802',
557         'ensp',
558         '803',
559         'emsp',
560         '809',
561         'thinsp',
562         '80c',
563         'zwnj',
564         '80d',
565         'zwj',
566         '80e',
567         'lrm',
568         '80f',
569         'rlm',
570         '80j',
571         'ndash',
572         '80k',
573         'mdash',
574         '80o',
575         'lsquo',
576         '80p',
577         'rsquo',
578         '80q',
579         'sbquo',
580         '80s',
581         'ldquo',
582         '80t',
583         'rdquo',
584         '80u',
585         'bdquo',
586         '810',
587         'dagger',
588         '811',
589         'Dagger',
590         '81g',
591         'permil',
592         '81p',
593         'lsaquo',
594         '81q',
595         'rsaquo',
596         '85c',
597         'euro'
598     ],
599
600          
601     /**
602      * Encodes the specified string using raw entities. This means only the required XML base entities will be encoded.
603      *
604      * @method encodeRaw
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.
608      */
609     encodeRaw: function(text, attr)
610     {
611         var t = this;
612         return text.replace(attr ? this.attrsCharsRegExp : this.textCharsRegExp, function(chr) {
613             return t.baseEntities[chr] || chr;
614         });
615     },
616     /**
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.
620      *
621      * @method encodeAllRaw
622      * @param {String} text Text to encode.
623      * @return {String} Entity encoded text.
624      */
625     encodeAllRaw: function(text) {
626         var t = this;
627         return ('' + text).replace(this.rawCharsRegExp, function(chr) {
628             return t.baseEntities[chr] || chr;
629         });
630     },
631     /**
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.
634      *
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.
639      */
640     encodeNumeric: function(text, attr) {
641         var t = this;
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) + ';';
646             }
647             return t.baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';';
648         });
649     },
650     /**
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.
653      *
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.
659      */
660     encodeNamed: function(text, attr, entities) {
661         var t = this;
662         entities = entities || this.namedEntities;
663         return text.replace(attr ? this.attrsCharsRegExp : this.textCharsRegExp, function(chr) {
664             return t.baseEntities[chr] || entities[chr] || chr;
665         });
666     },
667     /**
668      * Returns an encode function based on the name(s) and it's optional entities.
669      *
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.
674      */
675     getEncodeFunc: function(name, entities) {
676         entities = this.buildEntitiesLookup(entities) || this.namedEntities;
677         var t = this;
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;
681             });
682         }
683
684         function encodeCustomNamed(text, attr) {
685             return t.encodeNamed(text, attr, entities);
686         }
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;
692         }
693         // Named encoder
694         if (name.named) {
695             // Custom names
696             if (entities) {
697                 return encodeCustomNamed;
698             }
699             return this.encodeNamed;
700         }
701         // Numeric
702         if (name.numeric) {
703             return this.encodeNumeric;
704         }
705         // Raw encoder
706         return this.encodeRaw;
707     },
708     /**
709      * Decodes the specified string, this will replace entities with raw UTF characters.
710      *
711      * @method decode
712      * @param {String} text Text to entity decode.
713      * @return {String} Entity decoded string.
714      */
715     decode: function(text)
716     {
717         var  t = this;
718         return text.replace(this.entityRegExp, function(all, numeric) {
719             if (numeric) {
720                 numeric = 'x' === numeric.charAt(0).toLowerCase() ? parseInt(numeric.substr(1), 16) : parseInt(numeric, 10);
721                 // Support upper UTF
722                 if (numeric > 65535) {
723                     numeric -= 65536;
724                     return String.fromCharCode(55296 + (numeric >> 10), 56320 + (1023 & numeric));
725                 }
726                 return t.asciiMap[numeric] || String.fromCharCode(numeric);
727             }
728             return t.reverseEntities[all] || t.namedEntities[all] || t.nativeDecode(all);
729         });
730     },
731     nativeDecode : function (text) {
732         return text;
733     },
734     makeMap : function (items, delim, map) {
735                 var i;
736                 items = items || [];
737                 delim = delim || ',';
738                 if (typeof items == "string") {
739                         items = items.split(delim);
740                 }
741                 map = map || {};
742                 i = items.length;
743                 while (i--) {
744                         map[items[i]] = {};
745                 }
746                 return map;
747         },
748     
749     
750     
751 Roo.htmleditor.TidyEntities.init();