@xmldom/xmldom 0.8.2 → 0.9.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/dom.js CHANGED
@@ -1,5 +1,7 @@
1
1
  var conventions = require("./conventions");
2
-
2
+ var isHTMLRawTextElement = conventions.isHTMLRawTextElement;
3
+ var isHTMLVoidElement = conventions.isHTMLVoidElement;
4
+ var MIME_TYPE = conventions.MIME_TYPE;
3
5
  var NAMESPACE = conventions.NAMESPACE;
4
6
 
5
7
  /**
@@ -62,7 +64,9 @@ function arrayIncludes (list) {
62
64
 
63
65
  function copy(src,dest){
64
66
  for(var p in src){
65
- dest[p] = src[p];
67
+ if (Object.prototype.hasOwnProperty.call(src, p)) {
68
+ dest[p] = src[p];
69
+ }
66
70
  }
67
71
  }
68
72
 
@@ -156,23 +160,23 @@ NodeList.prototype = {
156
160
  * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
157
161
  * @standard level1
158
162
  */
159
- length:0,
163
+ length:0,
160
164
  /**
161
165
  * Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
162
166
  * @standard level1
163
- * @param index unsigned long
167
+ * @param index unsigned long
164
168
  * Index into the collection.
165
169
  * @return Node
166
- * The node at the indexth position in the NodeList, or null if that is not a valid index.
170
+ * The node at the indexth position in the NodeList, or null if that is not a valid index.
167
171
  */
168
172
  item: function(index) {
169
173
  return this[index] || null;
170
174
  },
171
- toString:function(isHTML,nodeFilter){
175
+ toString: function (nodeFilter) {
172
176
  for(var buf = [], i = 0;i<this.length;i++){
173
- serializeToString(this[i],buf,isHTML,nodeFilter);
177
+ serializeToString(this[i], buf, nodeFilter)
174
178
  }
175
- return buf.join('');
179
+ return buf.join('')
176
180
  }
177
181
  };
178
182
 
@@ -207,7 +211,7 @@ _extends(LiveNodeList,NodeList);
207
211
  * but this is simply to allow convenient enumeration of the contents of a NamedNodeMap,
208
212
  * and does not imply that the DOM specifies an order to these Nodes.
209
213
  * NamedNodeMap objects in the DOM are live.
210
- * used for attributes or DocumentType entities
214
+ * used for attributes or DocumentType entities
211
215
  */
212
216
  function NamedNodeMap() {
213
217
  };
@@ -296,10 +300,10 @@ NamedNodeMap.prototype = {
296
300
  var attr = this.getNamedItem(key);
297
301
  _removeNamedNode(this._ownerElement,this,attr);
298
302
  return attr;
299
-
300
-
303
+
304
+
301
305
  },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
302
-
306
+
303
307
  //for level2
304
308
  removeNamedItemNS:function(namespaceURI,localName){
305
309
  var attr = this.getNamedItemNS(namespaceURI,localName);
@@ -359,15 +363,17 @@ DOMImplementation.prototype = {
359
363
  * Creates an XML Document object of the specified type with its document element.
360
364
  *
361
365
  * __It behaves slightly different from the description in the living standard__:
362
- * - There is no interface/class `XMLDocument`, it returns a `Document` instance.
363
- * - `contentType`, `encoding`, `mode`, `origin`, `url` fields are currently not declared.
364
- * - this implementation is not validating names or qualified names
365
- * (when parsing XML strings, the SAX parser takes care of that)
366
+ * - There is no interface/class `XMLDocument`, it returns a `Document` instance (with it's `type` set to `'xml'`).
367
+ * - `encoding`, `mode`, `origin`, `url` fields are currently not declared.
368
+ * - The methods provided by this implementation are not validating names or qualified names.
369
+ * (They are only validated by the SAX parser when calling `DOMParser.parseFromString`)
366
370
  *
367
- * @param {string|null} namespaceURI
371
+ * @param {string | null} namespaceURI
368
372
  * @param {string} qualifiedName
369
- * @param {DocumentType=null} doctype
370
- * @returns {Document}
373
+ * @param {DocumentType | null} [doctype=null]
374
+ * @returns {Document} the XML document
375
+ *
376
+ * @see #createHTMLDocument
371
377
  *
372
378
  * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocument MDN
373
379
  * @see https://www.w3.org/TR/DOM-Level-2-Core/core.html#Level-2-Core-DOM-createDocument DOM Level 2 Core (initial)
@@ -378,7 +384,13 @@ DOMImplementation.prototype = {
378
384
  * @see https://www.w3.org/TR/xml-names/#ns-qualnames XML Namespaces: Qualified names
379
385
  */
380
386
  createDocument: function(namespaceURI, qualifiedName, doctype){
381
- var doc = new Document();
387
+ var contentType = MIME_TYPE.XML_APPLICATION;
388
+ if (namespaceURI === NAMESPACE.HTML) {
389
+ contentType = MIME_TYPE.XML_XHTML_APPLICATION;
390
+ } else if (namespaceURI === NAMESPACE.SVG) {
391
+ contentType = MIME_TYPE.XML_SVG_IMAGE
392
+ }
393
+ var doc = new Document({contentType: contentType});
382
394
  doc.implementation = this;
383
395
  doc.childNodes = new NodeList();
384
396
  doc.doctype = doctype || null;
@@ -397,6 +409,7 @@ DOMImplementation.prototype = {
397
409
  * __This behavior is slightly different from the in the specs__:
398
410
  * - this implementation is not validating names or qualified names
399
411
  * (when parsing XML strings, the SAX parser takes care of that)
412
+ * - `encoding`, `mode`, `origin`, `url` fields are currently not declared.
400
413
  *
401
414
  * @param {string} qualifiedName
402
415
  * @param {string} [publicId]
@@ -420,6 +433,40 @@ DOMImplementation.prototype = {
420
433
  node.systemId = systemId || '';
421
434
 
422
435
  return node;
436
+ },
437
+ /**
438
+ * Returns an HTML document, that might already have a basic DOM structure.
439
+ *
440
+ * __It behaves slightly different from the description in the living standard__:
441
+ * - If the first argument is `false` no initial nodes are added (steps 3-7 in the specs are omitted)
442
+ * - `encoding`, `mode`, `origin`, `url` fields are currently not declared.
443
+ *
444
+ * @param {string | false} [title]
445
+ * @returns {Document} The HTML document
446
+ *
447
+ * @see https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
448
+ * @see https://dom.spec.whatwg.org/#html-document
449
+ */
450
+ createHTMLDocument: function(title) {
451
+ var doc = new Document({contentType: MIME_TYPE.HTML})
452
+ doc.implementation = this
453
+ doc.childNodes = new NodeList()
454
+ if (title !== false) {
455
+ doc.doctype = this.createDocumentType('html')
456
+ doc.doctype.ownerDocument = this;
457
+ doc.appendChild(doc.doctype);
458
+ var htmlNode = doc.createElement('html')
459
+ doc.appendChild(htmlNode)
460
+ var headNode = doc.createElement('head')
461
+ htmlNode.appendChild(headNode)
462
+ if (typeof title === 'string') {
463
+ var titleNode = doc.createElement('title');
464
+ titleNode.appendChild(doc.createTextNode(title))
465
+ headNode.appendChild(titleNode)
466
+ }
467
+ htmlNode.appendChild(doc.createElement('body'))
468
+ }
469
+ return doc
423
470
  }
424
471
  };
425
472
 
@@ -427,7 +474,6 @@ DOMImplementation.prototype = {
427
474
  /**
428
475
  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
429
476
  */
430
-
431
477
  function Node() {
432
478
  };
433
479
 
@@ -445,10 +491,10 @@ Node.prototype = {
445
491
  prefix : null,
446
492
  localName : null,
447
493
  // Modified in DOM Level 2:
448
- insertBefore:function(newChild, refChild){//raises
494
+ insertBefore:function(newChild, refChild){//raises
449
495
  return _insertBefore(this,newChild,refChild);
450
496
  },
451
- replaceChild:function(newChild, oldChild){//raises
497
+ replaceChild:function(newChild, oldChild){//raises
452
498
  this.insertBefore(newChild,oldChild);
453
499
  if(oldChild){
454
500
  this.removeChild(oldChild);
@@ -509,9 +555,9 @@ Node.prototype = {
509
555
  //console.dir(map)
510
556
  if(map){
511
557
  for(var n in map){
512
- if(map[n] == namespaceURI){
513
- return n;
514
- }
558
+ if (Object.prototype.hasOwnProperty.call(map, n) && map[n] === namespaceURI) {
559
+ return n;
560
+ }
515
561
  }
516
562
  }
517
563
  el = el.nodeType == ATTRIBUTE_NODE?el.ownerDocument : el.parentNode;
@@ -525,7 +571,7 @@ Node.prototype = {
525
571
  var map = el._nsMap;
526
572
  //console.dir(map)
527
573
  if(map){
528
- if(prefix in map){
574
+ if(Object.prototype.hasOwnProperty.call(map, prefix)){
529
575
  return map[prefix] ;
530
576
  }
531
577
  }
@@ -568,9 +614,48 @@ function _visitNode(node,callback){
568
614
  }
569
615
  }
570
616
 
571
-
572
-
573
- function Document(){
617
+ /**
618
+ * @typedef DocumentOptions
619
+ * @property {string} [contentType=MIME_TYPE.XML_APPLICATION]
620
+ */
621
+ /**
622
+ * The Document interface describes the common properties and methods for any kind of document.
623
+ *
624
+ * It should usually be created using `new DOMImplementation().createDocument(...)`
625
+ * or `new DOMImplementation().createHTMLDocument(...)`.
626
+ *
627
+ * The constructor is considered a private API and offers to initially set the `contentType` property
628
+ * via it's options parameter.
629
+ *
630
+ * @param {DocumentOptions} [options]
631
+ * @private
632
+ * @constructor
633
+ *
634
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Document
635
+ * @see https://dom.spec.whatwg.org/#interface-document
636
+ */
637
+ function Document(options){
638
+ var opt = options || {};
639
+ /**
640
+ * The mime type of the document is determined at creation time and can not be modified.
641
+ *
642
+ * @type {string}
643
+ * @readonly
644
+ *
645
+ * @see https://dom.spec.whatwg.org/#concept-document-content-type
646
+ * @see DOMImplementation
647
+ * @see MIME_TYPE
648
+ */
649
+ this.contentType = opt.contentType || MIME_TYPE.XML_APPLICATION
650
+ /**
651
+ *
652
+ * @type {'html' | 'xml'}
653
+ * @readonly
654
+ *
655
+ * @see https://dom.spec.whatwg.org/#concept-document-type
656
+ * @see DOMImplementation
657
+ */
658
+ this.type = MIME_TYPE.isHTML(this.contentType) ? 'html' : 'xml'
574
659
  }
575
660
 
576
661
  function _onAddAttribute(doc,el,newAttr){
@@ -675,8 +760,8 @@ function _insertBefore(parentNode,newChild,nextChild){
675
760
 
676
761
  newFirst.previousSibling = pre;
677
762
  newLast.nextSibling = nextChild;
678
-
679
-
763
+
764
+
680
765
  if(pre){
681
766
  pre.nextSibling = newFirst;
682
767
  }else{
@@ -727,7 +812,12 @@ function _appendSingleChild (parentNode, newChild) {
727
812
  }
728
813
 
729
814
  Document.prototype = {
730
- //implementation : null,
815
+ /**
816
+ * The implementation that created this document
817
+ * @readonly
818
+ * @type DOMImplementation
819
+ */
820
+ implementation : null,
731
821
  nodeName : '#document',
732
822
  nodeType : DOCUMENT_NODE,
733
823
  /**
@@ -824,10 +914,34 @@ Document.prototype = {
824
914
  });
825
915
  },
826
916
 
827
- //document factory method:
917
+ /**
918
+ * Creates a new `Element` that is owned by this `Document`.
919
+ * In HTML Documents `localName` is the lower cased `tagName`,
920
+ * otherwise no transformation is being applied.
921
+ * When `contentType` implies the HTML namespace, it will be set as `namespaceURI`.
922
+ *
923
+ * __This implementation differs from the specification:__
924
+ * - The provided name is not checked against the `Name` production,
925
+ * so no related error will be thrown.
926
+ * - There is no interface `HTMLElement`, it is always an `Element`.
927
+ * - There is no support for a second argument to indicate using custom elements.
928
+ *
929
+ * @param {string} tagName
930
+ * @return {Element}
931
+ *
932
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement
933
+ * @see https://dom.spec.whatwg.org/#dom-document-createelement
934
+ * @see https://dom.spec.whatwg.org/#concept-create-element
935
+ */
828
936
  createElement : function(tagName){
829
937
  var node = new Element();
830
938
  node.ownerDocument = this;
939
+ if (this.type === 'html') {
940
+ tagName = tagName.toLowerCase()
941
+ }
942
+ if (MIME_TYPE.hasDefaultHTMLNamespace(this.contentType)) {
943
+ node.namespaceURI = NAMESPACE.HTML
944
+ }
831
945
  node.nodeName = tagName;
832
946
  node.tagName = tagName;
833
947
  node.localName = tagName;
@@ -867,9 +981,30 @@ Document.prototype = {
867
981
  node.nodeValue= node.data = data;
868
982
  return node;
869
983
  },
870
- createAttribute : function(name){
984
+ /**
985
+ * Creates an `Attr` node that is owned by this document.
986
+ * In HTML Documents `localName` is the lower cased `name`,
987
+ * otherwise no transformation is being applied.
988
+ *
989
+ * __This implementation differs from the specification:__
990
+ * - The provided name is not checked against the `Name` production,
991
+ * so no related error will be thrown.
992
+ *
993
+ * @param {string} name
994
+ * @return {Attr}
995
+ *
996
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createAttribute
997
+ * @see https://dom.spec.whatwg.org/#dom-document-createattribute
998
+ */
999
+ createAttribute: function(name){
1000
+ if (this.type === 'html') {
1001
+ name = name.toLowerCase()
1002
+ }
1003
+ return this._createAttribute(name);
1004
+ },
1005
+ _createAttribute: function(name){
871
1006
  var node = new Attr();
872
- node.ownerDocument = this;
1007
+ node.ownerDocument = this;
873
1008
  node.name = name;
874
1009
  node.nodeName = name;
875
1010
  node.localName = name;
@@ -929,6 +1064,12 @@ function Element() {
929
1064
  };
930
1065
  Element.prototype = {
931
1066
  nodeType : ELEMENT_NODE,
1067
+ getQualifiedName: function () {
1068
+ return this.prefix ? this.prefix+':'+this.localName : this.localName
1069
+ },
1070
+ _isInHTMLDocumentAndNamespace: function () {
1071
+ return this.ownerDocument.type === 'html' && this.namespaceURI === NAMESPACE.HTML;
1072
+ },
932
1073
  hasAttribute : function(name){
933
1074
  return this.getAttributeNode(name)!=null;
934
1075
  },
@@ -937,10 +1078,16 @@ Element.prototype = {
937
1078
  return attr && attr.value || '';
938
1079
  },
939
1080
  getAttributeNode : function(name){
1081
+ if (this._isInHTMLDocumentAndNamespace()) {
1082
+ name = name.toLowerCase()
1083
+ }
940
1084
  return this.attributes.getNamedItem(name);
941
1085
  },
942
1086
  setAttribute : function(name, value){
943
- var attr = this.ownerDocument.createAttribute(name);
1087
+ if (this._isInHTMLDocumentAndNamespace()) {
1088
+ name = name.toLowerCase()
1089
+ }
1090
+ var attr = this.ownerDocument._createAttribute(name)
944
1091
  attr.value = attr.nodeValue = "" + value;
945
1092
  this.setAttributeNode(attr)
946
1093
  },
@@ -948,8 +1095,8 @@ Element.prototype = {
948
1095
  var attr = this.getAttributeNode(name)
949
1096
  attr && this.removeAttributeNode(attr);
950
1097
  },
951
-
952
- //four real opeartion method
1098
+
1099
+ // four real operation method
953
1100
  appendChild:function(newChild){
954
1101
  if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
955
1102
  return this.insertBefore(newChild,null);
@@ -972,7 +1119,7 @@ Element.prototype = {
972
1119
  var old = this.getAttributeNodeNS(namespaceURI, localName);
973
1120
  old && this.removeAttributeNode(old);
974
1121
  },
975
-
1122
+
976
1123
  hasAttributeNS : function(namespaceURI, localName){
977
1124
  return this.getAttributeNodeNS(namespaceURI, localName)!=null;
978
1125
  },
@@ -988,13 +1135,51 @@ Element.prototype = {
988
1135
  getAttributeNodeNS : function(namespaceURI, localName){
989
1136
  return this.attributes.getNamedItemNS(namespaceURI, localName);
990
1137
  },
991
-
992
- getElementsByTagName : function(tagName){
1138
+
1139
+ /**
1140
+ * Returns a LiveNodeList of elements with the given qualifiedName.
1141
+ * Searching for all descendants can be done by passing `*` as `qualifiedName`.
1142
+ *
1143
+ * All descendants of the specified element are searched, but not the element itself.
1144
+ * The returned list is live, which means it updates itself with the DOM tree automatically.
1145
+ * Therefore, there is no need to call `Element.getElementsByTagName()`
1146
+ * with the same element and arguments repeatedly if the DOM changes in between calls.
1147
+ *
1148
+ * When called on an HTML element in an HTML document,
1149
+ * `getElementsByTagName` lower-cases the argument before searching for it.
1150
+ * This is undesirable when trying to match camel-cased SVG elements
1151
+ * (such as `<linearGradient>`) in an HTML document.
1152
+ * Instead, use `Element.getElementsByTagNameNS()`,
1153
+ * which preserves the capitalization of the tag name.
1154
+ *
1155
+ * `Element.getElementsByTagName` is similar to `Document.getElementsByTagName()`,
1156
+ * except that it only searches for elements that are descendants of the specified element.
1157
+ *
1158
+ * @param {string} qualifiedName
1159
+ * @return {LiveNodeList}
1160
+ *
1161
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByTagName
1162
+ * @see https://dom.spec.whatwg.org/#concept-getelementsbytagname
1163
+ */
1164
+ getElementsByTagName : function(qualifiedName){
1165
+ var isHTMLDocument = (this.nodeType === DOCUMENT_NODE ? this : this.ownerDocument).type === 'html'
1166
+ var lowerQualifiedName = qualifiedName.toLowerCase()
993
1167
  return new LiveNodeList(this,function(base){
994
1168
  var ls = [];
995
- _visitNode(base,function(node){
996
- if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){
1169
+ _visitNode(base, function(node) {
1170
+ if (node === base || node.nodeType !== ELEMENT_NODE) {
1171
+ return
1172
+ }
1173
+ if (qualifiedName === '*') {
997
1174
  ls.push(node);
1175
+ } else {
1176
+ var nodeQualifiedName = node.getQualifiedName();
1177
+ var matchingQName = isHTMLDocument && node.namespaceURI === NAMESPACE.HTML
1178
+ ? lowerQualifiedName
1179
+ : qualifiedName
1180
+ if(nodeQualifiedName === matchingQName){
1181
+ ls.push(node);
1182
+ }
998
1183
  }
999
1184
  });
1000
1185
  return ls;
@@ -1009,7 +1194,7 @@ Element.prototype = {
1009
1194
  }
1010
1195
  });
1011
1196
  return ls;
1012
-
1197
+
1013
1198
  });
1014
1199
  }
1015
1200
  };
@@ -1038,7 +1223,7 @@ CharacterData.prototype = {
1038
1223
  },
1039
1224
  insertData: function(offset,text) {
1040
1225
  this.replaceData(offset,0,text);
1041
-
1226
+
1042
1227
  },
1043
1228
  appendChild:function(newChild){
1044
1229
  throw new Error(ExceptionMessage[HIERARCHY_REQUEST_ERR])
@@ -1123,29 +1308,26 @@ function ProcessingInstruction() {
1123
1308
  ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
1124
1309
  _extends(ProcessingInstruction,Node);
1125
1310
  function XMLSerializer(){}
1126
- XMLSerializer.prototype.serializeToString = function(node,isHtml,nodeFilter){
1127
- return nodeSerializeToString.call(node,isHtml,nodeFilter);
1311
+ XMLSerializer.prototype.serializeToString = function (node, nodeFilter) {
1312
+ return nodeSerializeToString.call(node, nodeFilter);
1128
1313
  }
1129
1314
  Node.prototype.toString = nodeSerializeToString;
1130
- function nodeSerializeToString(isHtml,nodeFilter){
1315
+ function nodeSerializeToString(nodeFilter) {
1131
1316
  var buf = [];
1132
- var refNode = this.nodeType == 9 && this.documentElement || this;
1317
+ var refNode = this.nodeType === DOCUMENT_NODE && this.documentElement || this;
1133
1318
  var prefix = refNode.prefix;
1134
1319
  var uri = refNode.namespaceURI;
1135
-
1320
+
1136
1321
  if(uri && prefix == null){
1137
- //console.log(prefix)
1138
1322
  var prefix = refNode.lookupPrefix(uri);
1139
1323
  if(prefix == null){
1140
- //isHTML = true;
1141
1324
  var visibleNamespaces=[
1142
1325
  {namespace:uri,prefix:null}
1143
1326
  //{namespace:uri,prefix:''}
1144
1327
  ]
1145
1328
  }
1146
1329
  }
1147
- serializeToString(this,buf,isHtml,nodeFilter,visibleNamespaces);
1148
- //console.log('###',this.nodeType,uri,prefix,buf.join(''))
1330
+ serializeToString(this,buf,nodeFilter,visibleNamespaces);
1149
1331
  return buf.join('');
1150
1332
  }
1151
1333
 
@@ -1165,8 +1347,8 @@ function needNamespaceDefine(node, isHTML, visibleNamespaces) {
1165
1347
  if (prefix === "xml" && uri === NAMESPACE.XML || uri === NAMESPACE.XMLNS) {
1166
1348
  return false;
1167
1349
  }
1168
-
1169
- var i = visibleNamespaces.length
1350
+
1351
+ var i = visibleNamespaces.length
1170
1352
  while (i--) {
1171
1353
  var ns = visibleNamespaces[i];
1172
1354
  // get namespace prefix
@@ -1193,10 +1375,12 @@ function addSerializedAttribute(buf, qualifiedName, value) {
1193
1375
  buf.push(' ', qualifiedName, '="', value.replace(/[<>&"\t\n\r]/g, _xmlEncoder), '"')
1194
1376
  }
1195
1377
 
1196
- function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
1378
+ function serializeToString (node, buf, nodeFilter, visibleNamespaces) {
1197
1379
  if (!visibleNamespaces) {
1198
1380
  visibleNamespaces = [];
1199
1381
  }
1382
+ var doc = node.nodeType === DOCUMENT_NODE ? node : node.ownerDocument
1383
+ var isHTML = doc.type === 'html'
1200
1384
 
1201
1385
  if(nodeFilter){
1202
1386
  node = nodeFilter(node);
@@ -1217,8 +1401,6 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
1217
1401
  var len = attrs.length;
1218
1402
  var child = node.firstChild;
1219
1403
  var nodeName = node.tagName;
1220
-
1221
- isHTML = NAMESPACE.isHTML(node.namespaceURI) || isHTML
1222
1404
 
1223
1405
  var prefixedNodeName = nodeName
1224
1406
  if (!isHTML && !node.prefix && node.namespaceURI) {
@@ -1273,39 +1455,43 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
1273
1455
  addSerializedAttribute(buf, prefix ? 'xmlns:' + prefix : "xmlns", uri);
1274
1456
  visibleNamespaces.push({ prefix: prefix, namespace:uri });
1275
1457
  }
1276
- serializeToString(attr,buf,isHTML,nodeFilter,visibleNamespaces);
1458
+ serializeToString(attr,buf,nodeFilter,visibleNamespaces);
1277
1459
  }
1278
1460
 
1279
- // add namespace for current node
1461
+ // add namespace for current node
1280
1462
  if (nodeName === prefixedNodeName && needNamespaceDefine(node, isHTML, visibleNamespaces)) {
1281
1463
  var prefix = node.prefix||'';
1282
1464
  var uri = node.namespaceURI;
1283
1465
  addSerializedAttribute(buf, prefix ? 'xmlns:' + prefix : "xmlns", uri);
1284
1466
  visibleNamespaces.push({ prefix: prefix, namespace:uri });
1285
1467
  }
1286
-
1287
- if(child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)){
1288
- buf.push('>');
1468
+ // in XML elements can be closed when they have no children
1469
+ var canCloseTag = !child;
1470
+ if (canCloseTag && (isHTML || NAMESPACE.isHTML(node.namespaceURI))) {
1471
+ // in HTML (doc or ns) only void elements can be closed right away
1472
+ canCloseTag = isHTMLVoidElement(nodeName)
1473
+ }
1474
+ if (canCloseTag) {
1475
+ buf.push("/>");
1476
+ } else {
1477
+ buf.push(">");
1289
1478
  //if is cdata child node
1290
- if(isHTML && /^script$/i.test(nodeName)){
1479
+ if (isHTML && isHTMLRawTextElement(nodeName)) {
1291
1480
  while(child){
1292
1481
  if(child.data){
1293
1482
  buf.push(child.data);
1294
1483
  }else{
1295
- serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice());
1484
+ serializeToString(child, buf, nodeFilter, visibleNamespaces.slice());
1296
1485
  }
1297
1486
  child = child.nextSibling;
1298
1487
  }
1299
- }else
1300
- {
1488
+ } else {
1301
1489
  while(child){
1302
- serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice());
1490
+ serializeToString(child, buf, nodeFilter, visibleNamespaces.slice());
1303
1491
  child = child.nextSibling;
1304
1492
  }
1305
1493
  }
1306
- buf.push('</',prefixedNodeName,'>');
1307
- }else{
1308
- buf.push('/>');
1494
+ buf.push("</", prefixedNodeName, ">");
1309
1495
  }
1310
1496
  // remove added visible namespaces
1311
1497
  //visibleNamespaces.length = startVisibleNamespaces;
@@ -1314,7 +1500,7 @@ function serializeToString(node,buf,isHTML,nodeFilter,visibleNamespaces){
1314
1500
  case DOCUMENT_FRAGMENT_NODE:
1315
1501
  var child = node.firstChild;
1316
1502
  while(child){
1317
- serializeToString(child, buf, isHTML, nodeFilter, visibleNamespaces.slice());
1503
+ serializeToString(child, buf, nodeFilter, visibleNamespaces.slice());
1318
1504
  child = child.nextSibling;
1319
1505
  }
1320
1506
  return;
@@ -1424,11 +1610,13 @@ function importNode(doc,node,deep){
1424
1610
  // attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
1425
1611
  function cloneNode(doc,node,deep){
1426
1612
  var node2 = new node.constructor();
1427
- for(var n in node){
1428
- var v = node[n];
1429
- if(typeof v != 'object' ){
1430
- if(v != node2[n]){
1431
- node2[n] = v;
1613
+ for (var n in node) {
1614
+ if (Object.prototype.hasOwnProperty.call(node, n)) {
1615
+ var v = node[n];
1616
+ if (typeof v != "object") {
1617
+ if (v != node2[n]) {
1618
+ node2[n] = v;
1619
+ }
1432
1620
  }
1433
1621
  }
1434
1622
  }
@@ -1496,7 +1684,7 @@ try{
1496
1684
  }
1497
1685
  }
1498
1686
  })
1499
-
1687
+
1500
1688
  function getTextContent(node){
1501
1689
  switch(node.nodeType){
1502
1690
  case ELEMENT_NODE:
@@ -1523,12 +1711,11 @@ try{
1523
1711
  }catch(e){//ie8
1524
1712
  }
1525
1713
 
1526
- //if(typeof require == 'function'){
1527
- exports.DocumentType = DocumentType;
1528
- exports.DOMException = DOMException;
1529
- exports.DOMImplementation = DOMImplementation;
1530
- exports.Element = Element;
1531
- exports.Node = Node;
1532
- exports.NodeList = NodeList;
1533
- exports.XMLSerializer = XMLSerializer;
1534
- //}
1714
+ exports.Document = Document;
1715
+ exports.DocumentType = DocumentType;
1716
+ exports.DOMException = DOMException;
1717
+ exports.DOMImplementation = DOMImplementation;
1718
+ exports.Element = Element;
1719
+ exports.Node = Node;
1720
+ exports.NodeList = NodeList;
1721
+ exports.XMLSerializer = XMLSerializer;
package/lib/entities.js CHANGED
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  var freeze = require('./conventions').freeze;
2
4
 
3
5
  /**
package/lib/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  var dom = require('./dom')
2
4
  exports.DOMImplementation = dom.DOMImplementation
3
5
  exports.XMLSerializer = dom.XMLSerializer