]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/javascript/tiny_mce/classes/html/Entities.js
Release 6.5.0
[Github/sugarcrm.git] / include / javascript / tiny_mce / classes / html / Entities.js
1 /**
2  * Entities.js
3  *
4  * Copyright 2010, Moxiecode Systems AB
5  * Released under LGPL License.
6  *
7  * License: http://tinymce.moxiecode.com/license
8  * Contributing: http://tinymce.moxiecode.com/contributing
9  */
10
11 (function(tinymce) {
12         var namedEntities, baseEntities, reverseEntities,
13                 attrsCharsRegExp = /[&<>\"\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
14                 textCharsRegExp = /[<>&\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
15                 rawCharsRegExp = /[<>&\"\']/g,
16                 entityRegExp = /&(#x|#)?([\w]+);/g,
17                 asciiMap = {
18                                 128 : "\u20AC", 130 : "\u201A", 131 : "\u0192", 132 : "\u201E", 133 : "\u2026", 134 : "\u2020",
19                                 135 : "\u2021", 136 : "\u02C6", 137 : "\u2030", 138 : "\u0160", 139 : "\u2039", 140 : "\u0152",
20                                 142 : "\u017D", 145 : "\u2018", 146 : "\u2019", 147 : "\u201C", 148 : "\u201D", 149 : "\u2022",
21                                 150 : "\u2013", 151 : "\u2014", 152 : "\u02DC", 153 : "\u2122", 154 : "\u0161", 155 : "\u203A",
22                                 156 : "\u0153", 158 : "\u017E", 159 : "\u0178"
23                 };
24
25         // Raw entities
26         baseEntities = {
27                 '\"' : '&quot;', // Needs to be escaped since the YUI compressor would otherwise break the code
28                 "'" : '&#39;',
29                 '<' : '&lt;',
30                 '>' : '&gt;',
31                 '&' : '&amp;'
32         };
33
34         // Reverse lookup table for raw entities
35         reverseEntities = {
36                 '&lt;' : '<',
37                 '&gt;' : '>',
38                 '&amp;' : '&',
39                 '&quot;' : '"',
40                 '&apos;' : "'"
41         };
42
43         // Decodes text by using the browser
44         function nativeDecode(text) {
45                 var elm;
46
47                 elm = document.createElement("div");
48                 elm.innerHTML = text;
49
50                 return elm.textContent || elm.innerText || text;
51         };
52
53         // Build a two way lookup table for the entities
54         function buildEntitiesLookup(items, radix) {
55                 var i, chr, entity, lookup = {};
56
57                 if (items) {
58                         items = items.split(',');
59                         radix = radix || 10;
60
61                         // Build entities lookup table
62                         for (i = 0; i < items.length; i += 2) {
63                                 chr = String.fromCharCode(parseInt(items[i], radix));
64
65                                 // Only add non base entities
66                                 if (!baseEntities[chr]) {
67                                         entity = '&' + items[i + 1] + ';';
68                                         lookup[chr] = entity;
69                                         lookup[entity] = chr;
70                                 }
71                         }
72
73                         return lookup;
74                 }
75         };
76
77         // Unpack entities lookup where the numbers are in radix 32 to reduce the size
78         namedEntities = buildEntitiesLookup(
79                 '50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' +
80                 '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' +
81                 '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' +
82                 '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' +
83                 '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' +
84                 '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' +
85                 '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' +
86                 '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' +
87                 '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' +
88                 '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' +
89                 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' +
90                 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' +
91                 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' +
92                 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' +
93                 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' +
94                 '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' +
95                 '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' +
96                 '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' +
97                 '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' +
98                 '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' +
99                 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' +
100                 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' +
101                 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' +
102                 '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' +
103                 '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro'
104         , 32);
105
106         tinymce.html = tinymce.html || {};
107
108         /**
109          * Entity encoder class.
110          *
111          * @class tinymce.html.SaxParser
112          * @static
113          * @version 3.4
114          */
115         tinymce.html.Entities = {
116                 /**
117                  * Encodes the specified string using raw entities. This means only the required XML base entities will be endoded.
118                  *
119                  * @method encodeRaw
120                  * @param {String} text Text to encode.
121                  * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
122                  * @return {String} Entity encoded text.
123                  */
124                 encodeRaw : function(text, attr) {
125                         return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) {
126                                 return baseEntities[chr] || chr;
127                         });
128                 },
129
130                 /**
131                  * Encoded the specified text with both the attributes and text entities. This function will produce larger text contents
132                  * since it doesn't know if the context is within a attribute or text node. This was added for compatibility
133                  * and is exposed as the DOMUtils.encode function.
134                  *
135                  * @method encodeAllRaw
136                  * @param {String} text Text to encode.
137                  * @return {String} Entity encoded text.
138                  */
139                 encodeAllRaw : function(text) {
140                         return ('' + text).replace(rawCharsRegExp, function(chr) {
141                                 return baseEntities[chr] || chr;
142                         });
143                 },
144
145                 /**
146                  * Encodes the specified string using numeric entities. The core entities will be encoded as named ones but all non lower ascii characters
147                  * will be encoded into numeric entities.
148                  *
149                  * @method encodeNumeric
150                  * @param {String} text Text to encode.
151                  * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
152                  * @return {String} Entity encoded text.
153                  */
154                 encodeNumeric : function(text, attr) {
155                         return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) {
156                                 // Multi byte sequence convert it to a single entity
157                                 if (chr.length > 1)
158                                         return '&#' + (((chr.charCodeAt(0) - 0xD800) * 0x400) + (chr.charCodeAt(1) - 0xDC00) + 0x10000) + ';';
159
160                                 return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';';
161                         });
162                 },
163
164                 /**
165                  * Encodes the specified string using named entities. The core entities will be encoded as named ones but all non lower ascii characters
166                  * will be encoded into named entities.
167                  *
168                  * @method encodeNamed
169                  * @param {String} text Text to encode.
170                  * @param {Boolean} attr Optional flag to specify if the text is attribute contents.
171                  * @param {Object} entities Optional parameter with entities to use.
172                  * @return {String} Entity encoded text.
173                  */
174                 encodeNamed : function(text, attr, entities) {
175                         entities = entities || namedEntities;
176
177                         return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) {
178                                 return baseEntities[chr] || entities[chr] || chr;
179                         });
180                 },
181
182                 /**
183                  * Returns an encode function based on the name(s) and it's optional entities.
184                  *
185                  * @method getEncodeFunc
186                  * @param {String} name Comma separated list of encoders for example named,numeric.
187                  * @param {String} entities Optional parameter with entities to use instead of the built in set.
188                  * @return {function} Encode function to be used.
189                  */
190                 getEncodeFunc : function(name, entities) {
191                         var Entities = tinymce.html.Entities;
192
193                         entities = buildEntitiesLookup(entities) || namedEntities;
194
195                         function encodeNamedAndNumeric(text, attr) {
196                                 return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) {
197                                         return baseEntities[chr] || entities[chr] || '&#' + chr.charCodeAt(0) + ';' || chr;
198                                 });
199                         };
200
201                         function encodeCustomNamed(text, attr) {
202                                 return Entities.encodeNamed(text, attr, entities);
203                         };
204
205                         // Replace + with , to be compatible with previous TinyMCE versions
206                         name = tinymce.makeMap(name.replace(/\+/g, ','));
207
208                         // Named and numeric encoder
209                         if (name.named && name.numeric)
210                                 return encodeNamedAndNumeric;
211
212                         // Named encoder
213                         if (name.named) {
214                                 // Custom names
215                                 if (entities)
216                                         return encodeCustomNamed;
217
218                                 return Entities.encodeNamed;
219                         }
220
221                         // Numeric
222                         if (name.numeric)
223                                 return Entities.encodeNumeric;
224
225                         // Raw encoder
226                         return Entities.encodeRaw;
227                 },
228
229                 /**
230                  * Decodes the specified string, this will replace entities with raw UTF characters.
231                  *
232                  * @param {String} text Text to entity decode.
233                  * @return {String} Entity decoded string.
234                  */
235                 decode : function(text) {
236                         return text.replace(entityRegExp, function(all, numeric, value) {
237                                 if (numeric) {
238                                         value = parseInt(value, numeric.length === 2 ? 16 : 10);
239
240                                         // Support upper UTF
241                                         if (value > 0xFFFF) {
242                                                 value -= 0x10000;
243
244                                                 return String.fromCharCode(0xD800 + (value >> 10), 0xDC00 + (value & 0x3FF));
245                                         } else
246                                                 return asciiMap[value] || String.fromCharCode(value);
247                                 }
248
249                                 return reverseEntities[all] || namedEntities[all] || nativeDecode(all);
250                         });
251                 }
252         };
253 })(tinymce);