]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/debian/missing-sources/framework/Web/Javascripts/source/tinymce-405/classes/dom/Serializer.js
baculum: Add missing-sources directory in debian metadata structure
[bacula/bacula] / gui / baculum / debian / missing-sources / framework / Web / Javascripts / source / tinymce-405 / classes / dom / Serializer.js
1 /**
2  * Serializer.js
3  *
4  * Copyright, Moxiecode Systems AB
5  * Released under LGPL License.
6  *
7  * License: http://www.tinymce.com/license
8  * Contributing: http://www.tinymce.com/contributing
9  */
10
11 /**
12  * This class is used to serialize DOM trees into a string. Consult the TinyMCE Wiki API for
13  * more details and examples on how to use this class.
14  *
15  * @class tinymce.dom.Serializer
16  */
17 define("tinymce/dom/Serializer", [
18         "tinymce/dom/DOMUtils",
19         "tinymce/html/DomParser",
20         "tinymce/html/Entities",
21         "tinymce/html/Serializer",
22         "tinymce/html/Node",
23         "tinymce/html/Schema",
24         "tinymce/Env",
25         "tinymce/util/Tools"
26 ], function(DOMUtils, DomParser, Entities, Serializer, Node, Schema, Env, Tools) {
27         var each = Tools.each, trim = Tools.trim;
28         var DOM = DOMUtils.DOM;
29
30         /**
31          * Constructs a new DOM serializer class.
32          *
33          * @constructor
34          * @method Serializer
35          * @param {Object} settings Serializer settings object.
36          * @param {tinymce.Editor} editor Optional editor to bind events to and get schema/dom from.
37          */
38         return function(settings, editor) {
39                 var dom, schema, htmlParser;
40
41                 if (editor) {
42                         dom = editor.dom;
43                         schema = editor.schema;
44                 }
45
46                 // Default DOM and Schema if they are undefined
47                 dom = dom || DOM;
48                 schema = schema || new Schema(settings);
49                 settings.entity_encoding = settings.entity_encoding || 'named';
50                 settings.remove_trailing_brs = "remove_trailing_brs" in settings ? settings.remove_trailing_brs : true;
51
52                 htmlParser = new DomParser(settings, schema);
53
54                 // Convert move data-mce-src, data-mce-href and data-mce-style into nodes or process them if needed
55                 htmlParser.addAttributeFilter('src,href,style', function(nodes, name) {
56                         var i = nodes.length, node, value, internalName = 'data-mce-' + name;
57                         var urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope, undef;
58
59                         while (i--) {
60                                 node = nodes[i];
61
62                                 value = node.attributes.map[internalName];
63                                 if (value !== undef) {
64                                         // Set external name to internal value and remove internal
65                                         node.attr(name, value.length > 0 ? value : null);
66                                         node.attr(internalName, null);
67                                 } else {
68                                         // No internal attribute found then convert the value we have in the DOM
69                                         value = node.attributes.map[name];
70
71                                         if (name === "style") {
72                                                 value = dom.serializeStyle(dom.parseStyle(value), node.name);
73                                         } else if (urlConverter) {
74                                                 value = urlConverter.call(urlConverterScope, value, name, node.name);
75                                         }
76
77                                         node.attr(name, value.length > 0 ? value : null);
78                                 }
79                         }
80                 });
81
82                 // Remove internal classes mceItem<..> or mceSelected
83                 htmlParser.addAttributeFilter('class', function(nodes) {
84                         var i = nodes.length, node, value;
85
86                         while (i--) {
87                                 node = nodes[i];
88                                 value = node.attr('class').replace(/(?:^|\s)mce-item-\w+(?!\S)/g, '');
89                                 node.attr('class', value.length > 0 ? value : null);
90                         }
91                 });
92
93                 // Remove bookmark elements
94                 htmlParser.addAttributeFilter('data-mce-type', function(nodes, name, args) {
95                         var i = nodes.length, node;
96
97                         while (i--) {
98                                 node = nodes[i];
99
100                                 if (node.attributes.map['data-mce-type'] === 'bookmark' && !args.cleanup) {
101                                         node.remove();
102                                 }
103                         }
104                 });
105
106                 // Remove expando attributes
107                 htmlParser.addAttributeFilter('data-mce-expando', function(nodes, name) {
108                         var i = nodes.length;
109
110                         while (i--) {
111                                 nodes[i].attr(name, null);
112                         }
113                 });
114
115                 htmlParser.addNodeFilter('noscript', function(nodes) {
116                         var i = nodes.length, node;
117
118                         while (i--) {
119                                 node = nodes[i].firstChild;
120
121                                 if (node) {
122                                         node.value = Entities.decode(node.value);
123                                 }
124                         }
125                 });
126
127                 // Force script into CDATA sections and remove the mce- prefix also add comments around styles
128                 htmlParser.addNodeFilter('script,style', function(nodes, name) {
129                         var i = nodes.length, node, value;
130
131                         function trim(value) {
132                                 /*jshint maxlen:255 */
133                                 return value.replace(/(<!--\[CDATA\[|\]\]-->)/g, '\n')
134                                                 .replace(/^[\r\n]*|[\r\n]*$/g, '')
135                                                 .replace(/^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi, '')
136                                                 .replace(/\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g, '');
137                         }
138
139                         while (i--) {
140                                 node = nodes[i];
141                                 value = node.firstChild ? node.firstChild.value : '';
142
143                                 if (name === "script") {
144                                         // Remove mce- prefix from script elements and remove default text/javascript mime type (HTML5)
145                                         var type = (node.attr('type') || 'text/javascript').replace(/^mce\-/, '');
146                                         node.attr('type', type === 'text/javascript' ? null : type);
147
148                                         if (value.length > 0) {
149                                                 node.firstChild.value = '// <![CDATA[\n' + trim(value) + '\n// ]]>';
150                                         }
151                                 } else {
152                                         if (value.length > 0) {
153                                                 node.firstChild.value = '<!--\n' + trim(value) + '\n-->';
154                                         }
155                                 }
156                         }
157                 });
158
159                 // Convert comments to cdata and handle protected comments
160                 htmlParser.addNodeFilter('#comment', function(nodes) {
161                         var i = nodes.length, node;
162
163                         while (i--) {
164                                 node = nodes[i];
165
166                                 if (node.value.indexOf('[CDATA[') === 0) {
167                                         node.name = '#cdata';
168                                         node.type = 4;
169                                         node.value = node.value.replace(/^\[CDATA\[|\]\]$/g, '');
170                                 } else if (node.value.indexOf('mce:protected ') === 0) {
171                                         node.name = "#text";
172                                         node.type = 3;
173                                         node.raw = true;
174                                         node.value = unescape(node.value).substr(14);
175                                 }
176                         }
177                 });
178
179                 htmlParser.addNodeFilter('xml:namespace,input', function(nodes, name) {
180                         var i = nodes.length, node;
181
182                         while (i--) {
183                                 node = nodes[i];
184                                 if (node.type === 7) {
185                                         node.remove();
186                                 } else if (node.type === 1) {
187                                         if (name === "input" && !("type" in node.attributes.map)) {
188                                                 node.attr('type', 'text');
189                                         }
190                                 }
191                         }
192                 });
193
194                 // Fix list elements, TODO: Replace this later
195                 if (settings.fix_list_elements) {
196                         htmlParser.addNodeFilter('ul,ol', function(nodes) {
197                                 var i = nodes.length, node, parentNode;
198
199                                 while (i--) {
200                                         node = nodes[i];
201                                         parentNode = node.parent;
202
203                                         if (parentNode.name === 'ul' || parentNode.name === 'ol') {
204                                                 if (node.prev && node.prev.name === 'li') {
205                                                         node.prev.append(node);
206                                                 }
207                                         }
208                                 }
209                         });
210                 }
211
212                 // Remove internal data attributes
213                 htmlParser.addAttributeFilter('data-mce-src,data-mce-href,data-mce-style,data-mce-selected', function(nodes, name) {
214                         var i = nodes.length;
215
216                         while (i--) {
217                                 nodes[i].attr(name, null);
218                         }
219                 });
220
221                 // Return public methods
222                 return {
223                         /**
224                          * Schema instance that was used to when the Serializer was constructed.
225                          *
226                          * @field {tinymce.html.Schema} schema
227                          */
228                         schema: schema,
229
230                         /**
231                          * Adds a node filter function to the parser used by the serializer, the parser will collect the specified nodes by name
232                          * and then execute the callback ones it has finished parsing the document.
233                          *
234                          * @example
235                          * parser.addNodeFilter('p,h1', function(nodes, name) {
236                          *              for (var i = 0; i < nodes.length; i++) {
237                          *                      console.log(nodes[i].name);
238                          *              }
239                          * });
240                          * @method addNodeFilter
241                          * @method {String} name Comma separated list of nodes to collect.
242                          * @param {function} callback Callback function to execute once it has collected nodes.
243                          */
244                         addNodeFilter: htmlParser.addNodeFilter,
245
246                         /**
247                          * Adds a attribute filter function to the parser used by the serializer, the parser will
248                          * collect nodes that has the specified attributes
249                          * and then execute the callback ones it has finished parsing the document.
250                          *
251                          * @example
252                          * parser.addAttributeFilter('src,href', function(nodes, name) {
253                          *              for (var i = 0; i < nodes.length; i++) {
254                          *                      console.log(nodes[i].name);
255                          *              }
256                          * });
257                          * @method addAttributeFilter
258                          * @method {String} name Comma separated list of nodes to collect.
259                          * @param {function} callback Callback function to execute once it has collected nodes.
260                          */
261                         addAttributeFilter: htmlParser.addAttributeFilter,
262
263                         /**
264                          * Serializes the specified browser DOM node into a HTML string.
265                          *
266                          * @method serialize
267                          * @param {DOMNode} node DOM node to serialize.
268                          * @param {Object} args Arguments option that gets passed to event handlers.
269                          */
270                         serialize: function(node, args) {
271                                 var self = this, impl, doc, oldDoc, htmlSerializer, content;
272
273                                 // Explorer won't clone contents of script and style and the
274                                 // selected index of select elements are cleared on a clone operation.
275                                 if (Env.ie && dom.select('script,style,select,map').length > 0) {
276                                         content = node.innerHTML;
277                                         node = node.cloneNode(false);
278                                         dom.setHTML(node, content);
279                                 } else {
280                                         node = node.cloneNode(true);
281                                 }
282
283                                 // Nodes needs to be attached to something in WebKit/Opera
284                                 // This fix will make DOM ranges and make Sizzle happy!
285                                 impl = node.ownerDocument.implementation;
286                                 if (impl.createHTMLDocument) {
287                                         // Create an empty HTML document
288                                         doc = impl.createHTMLDocument("");
289
290                                         // Add the element or it's children if it's a body element to the new document
291                                         each(node.nodeName == 'BODY' ? node.childNodes : [node], function(node) {
292                                                 doc.body.appendChild(doc.importNode(node, true));
293                                         });
294
295                                         // Grab first child or body element for serialization
296                                         if (node.nodeName != 'BODY') {
297                                                 node = doc.body.firstChild;
298                                         } else {
299                                                 node = doc.body;
300                                         }
301
302                                         // set the new document in DOMUtils so createElement etc works
303                                         oldDoc = dom.doc;
304                                         dom.doc = doc;
305                                 }
306
307                                 args = args || {};
308                                 args.format = args.format || 'html';
309
310                                 // Don't wrap content if we want selected html
311                                 if (args.selection) {
312                                         args.forced_root_block = '';
313                                 }
314
315                                 // Pre process
316                                 if (!args.no_events) {
317                                         args.node = node;
318                                         self.onPreProcess(args);
319                                 }
320
321                                 // Setup serializer
322                                 htmlSerializer = new Serializer(settings, schema);
323
324                                 // Parse and serialize HTML
325                                 args.content = htmlSerializer.serialize(
326                                         htmlParser.parse(trim(args.getInner ? node.innerHTML : dom.getOuterHTML(node)), args)
327                                 );
328
329                                 // Replace all BOM characters for now until we can find a better solution
330                                 if (!args.cleanup) {
331                                         args.content = args.content.replace(/\uFEFF/g, '');
332                                 }
333
334                                 // Post process
335                                 if (!args.no_events) {
336                                         self.onPostProcess(args);
337                                 }
338
339                                 // Restore the old document if it was changed
340                                 if (oldDoc) {
341                                         dom.doc = oldDoc;
342                                 }
343
344                                 args.node = null;
345
346                                 return args.content;
347                         },
348
349                         /**
350                          * Adds valid elements rules to the serializers schema instance this enables you to specify things
351                          * like what elements should be outputted and what attributes specific elements might have.
352                          * Consult the Wiki for more details on this format.
353                          *
354                          * @method addRules
355                          * @param {String} rules Valid elements rules string to add to schema.
356                          */
357                         addRules: function(rules) {
358                                 schema.addValidElements(rules);
359                         },
360
361                         /**
362                          * Sets the valid elements rules to the serializers schema instance this enables you to specify things
363                          * like what elements should be outputted and what attributes specific elements might have.
364                          * Consult the Wiki for more details on this format.
365                          *
366                          * @method setRules
367                          * @param {String} rules Valid elements rules string.
368                          */
369                         setRules: function(rules) {
370                                 schema.setValidElements(rules);
371                         },
372
373                         onPreProcess: function(args) {
374                                 if (editor) {
375                                         editor.fire('PreProcess', args);
376                                 }
377                         },
378
379                         onPostProcess: function(args) {
380                                 if (editor) {
381                                         editor.fire('PostProcess', args);
382                                 }
383                         }
384                 };
385         };
386 });