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 down the DOM tree into a string using a Writer instance. |
|
13 * |
|
14 * |
|
15 * @example |
|
16 * new tinymce.html.Serializer().serialize(new tinymce.html.DomParser().parse('<p>text</p>')); |
|
17 * @class tinymce.html.Serializer |
|
18 * @version 3.4 |
|
19 */ |
|
20 define("tinymce/html/Serializer", [ |
|
21 "tinymce/html/Writer", |
|
22 "tinymce/html/Schema" |
|
23 ], function(Writer, Schema) { |
|
24 /** |
|
25 * Constructs a new Serializer instance. |
|
26 * |
|
27 * @constructor |
|
28 * @method Serializer |
|
29 * @param {Object} settings Name/value settings object. |
|
30 * @param {tinymce.html.Schema} schema Schema instance to use. |
|
31 */ |
|
32 return function(settings, schema) { |
|
33 var self = this, writer = new Writer(settings); |
|
34 |
|
35 settings = settings || {}; |
|
36 settings.validate = "validate" in settings ? settings.validate : true; |
|
37 |
|
38 self.schema = schema = schema || new Schema(); |
|
39 self.writer = writer; |
|
40 |
|
41 /** |
|
42 * Serializes the specified node into a string. |
|
43 * |
|
44 * @example |
|
45 * new tinymce.html.Serializer().serialize(new tinymce.html.DomParser().parse('<p>text</p>')); |
|
46 * @method serialize |
|
47 * @param {tinymce.html.Node} node Node instance to serialize. |
|
48 * @return {String} String with HTML based on DOM tree. |
|
49 */ |
|
50 self.serialize = function(node) { |
|
51 var handlers, validate; |
|
52 |
|
53 validate = settings.validate; |
|
54 |
|
55 handlers = { |
|
56 // #text |
|
57 3: function(node) { |
|
58 writer.text(node.value, node.raw); |
|
59 }, |
|
60 |
|
61 // #comment |
|
62 8: function(node) { |
|
63 writer.comment(node.value); |
|
64 }, |
|
65 |
|
66 // Processing instruction |
|
67 7: function(node) { |
|
68 writer.pi(node.name, node.value); |
|
69 }, |
|
70 |
|
71 // Doctype |
|
72 10: function(node) { |
|
73 writer.doctype(node.value); |
|
74 }, |
|
75 |
|
76 // CDATA |
|
77 4: function(node) { |
|
78 writer.cdata(node.value); |
|
79 }, |
|
80 |
|
81 // Document fragment |
|
82 11: function(node) { |
|
83 if ((node = node.firstChild)) { |
|
84 do { |
|
85 walk(node); |
|
86 } while ((node = node.next)); |
|
87 } |
|
88 } |
|
89 }; |
|
90 |
|
91 writer.reset(); |
|
92 |
|
93 function walk(node) { |
|
94 var handler = handlers[node.type], name, isEmpty, attrs, attrName, attrValue, sortedAttrs, i, l, elementRule; |
|
95 |
|
96 if (!handler) { |
|
97 name = node.name; |
|
98 isEmpty = node.shortEnded; |
|
99 attrs = node.attributes; |
|
100 |
|
101 // Sort attributes |
|
102 if (validate && attrs && attrs.length > 1) { |
|
103 sortedAttrs = []; |
|
104 sortedAttrs.map = {}; |
|
105 |
|
106 elementRule = schema.getElementRule(node.name); |
|
107 for (i = 0, l = elementRule.attributesOrder.length; i < l; i++) { |
|
108 attrName = elementRule.attributesOrder[i]; |
|
109 |
|
110 if (attrName in attrs.map) { |
|
111 attrValue = attrs.map[attrName]; |
|
112 sortedAttrs.map[attrName] = attrValue; |
|
113 sortedAttrs.push({name: attrName, value: attrValue}); |
|
114 } |
|
115 } |
|
116 |
|
117 for (i = 0, l = attrs.length; i < l; i++) { |
|
118 attrName = attrs[i].name; |
|
119 |
|
120 if (!(attrName in sortedAttrs.map)) { |
|
121 attrValue = attrs.map[attrName]; |
|
122 sortedAttrs.map[attrName] = attrValue; |
|
123 sortedAttrs.push({name: attrName, value: attrValue}); |
|
124 } |
|
125 } |
|
126 |
|
127 attrs = sortedAttrs; |
|
128 } |
|
129 |
|
130 writer.start(node.name, attrs, isEmpty); |
|
131 |
|
132 if (!isEmpty) { |
|
133 if ((node = node.firstChild)) { |
|
134 do { |
|
135 walk(node); |
|
136 } while ((node = node.next)); |
|
137 } |
|
138 |
|
139 writer.end(name); |
|
140 } |
|
141 } else { |
|
142 handler(node); |
|
143 } |
|
144 } |
|
145 |
|
146 // Serialize element and treat all non elements as fragments |
|
147 if (node.type == 1 && !settings.inner) { |
|
148 walk(node); |
|
149 } else { |
|
150 handlers[11](node); |
|
151 } |
|
152 |
|
153 return writer.getContent(); |
|
154 }; |
|
155 }; |
|
156 }); |
|