Serializer.js 3.6 KB

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