OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 "use strict"; |
| 6 |
| 7 installClass("ProcessingInstruction", function(ProcessingInstructionPrototype) { |
| 8 |
| 9 // Should be implemented as HTMLSerializer / XMLSerializer. |
| 10 function serializeAttributes(node) { |
| 11 var attributes = node.attributes; |
| 12 if (!attributes) |
| 13 return ''; |
| 14 var sink = ''; |
| 15 var attrs = []; |
| 16 for (var index = 0; index < attributes.length; ++index) { |
| 17 attrs.push(attributes[index]); |
| 18 } |
| 19 |
| 20 attrs.sort(function(a, b) { |
| 21 return a.name <= b.name ? -1 : 0; |
| 22 }).forEach(function(attr) { |
| 23 var attrName = attr.name; |
| 24 if (attrName.indexOf('_moz') == 0) |
| 25 return; |
| 26 var attrValue = attr.value; |
| 27 if (attrValue){ |
| 28 attrValue = String(attrValue).replace(/&/g, '&') |
| 29 .replace(/\u0022/g, '"') |
| 30 sink += ' ' + attrName + '="' + attrValue + '"'; |
| 31 } else { |
| 32 sink += ' ' + attrName; |
| 33 } |
| 34 }); |
| 35 return sink; |
| 36 } |
| 37 |
| 38 function serializeChildren(node, isXML) { |
| 39 var sink = ''; |
| 40 var child = node.firstChild; |
| 41 while (child) { |
| 42 sink += serialize(child, isXML); |
| 43 var nextSibling = child.nextSibling; |
| 44 if (child.nodeType == Node.TEXT_NODE && nextSibling && |
| 45 nextSibling.nodeType == Node.TEXT_NODE) { |
| 46 sink += '_'; |
| 47 } |
| 48 child = nextSibling; |
| 49 } |
| 50 return sink; |
| 51 } |
| 52 |
| 53 var _END_TAG_MISSIBLE = {'area':true,'base':true,'br':true,'col':true,'comma
nd':true,'embed':true,'frame':true, |
| 54 'hr':true,'img':true,'input':true,'keygen':true,'li
nk':true,'meta':true,'param':true, |
| 55 'source':true,'track':true,'wbr':true}; |
| 56 |
| 57 // FIXME: should implement this as HTMLSerializer to share the code with edi
ting? |
| 58 function serialize(node, isXML) { |
| 59 if (node.nodeType == Node.TEXT_NODE) { |
| 60 if (node.parentNode && node.parentNode.nodeType == Node.ELEMENT_NODE
&& node.parentNode.nodeName.toLowerCase() == 'script') |
| 61 return node.nodeValue; |
| 62 // Need to escape: &, < |
| 63 return node.nodeValue.replace(/&/g, '&').replace(/</g, '<').r
eplace(/>/g, '>'); |
| 64 } |
| 65 if (node.nodeType == Node.DOCUMENT_TYPE_NODE) { |
| 66 var sink = '<!DOCTYPE ' + node.name; |
| 67 if (node.publicId) { |
| 68 sink += ' PUBLIC "' + node.publicId + '"'; |
| 69 if (node.systemId) |
| 70 sink += ' "' + node.systemId + '"'; |
| 71 } |
| 72 sink += '>'; |
| 73 return sink; |
| 74 } |
| 75 if (node.nodeType == Node.PROCESSING_INSTRUCTION_NODE) { |
| 76 var sink = '<?' + node.target; |
| 77 if (node.nodeValue) |
| 78 sink += ' ' + node.nodeValue; |
| 79 sink += '?>'; |
| 80 return sink; |
| 81 } |
| 82 if (node.nodeType == Node.COMMENT_NODE) { |
| 83 return '<!-- ' + node.nodeValue + ' -->'; |
| 84 } |
| 85 if (node.nodeType != Node.ELEMENT_NODE) { |
| 86 // To support |Document| node, we iterate over child nodes. |
| 87 var sink = ''; |
| 88 for (var child = node.firstChild; child; child = child.nextSibling)
{ |
| 89 sink += serialize(child, isXML); |
| 90 } |
| 91 return sink.length ? sink : node.nodeValue; |
| 92 } |
| 93 |
| 94 var tagName = node.nodeName.toLowerCase(); |
| 95 var sink = '<' + node.nodeName + serializeAttributes(node) + '>'; |
| 96 |
| 97 if (tagName == 'template') { |
| 98 sink += serializeChildren(node.content, node.content instanceof XMLD
ocument); |
| 99 } else if (tagName == 'iframe') { |
| 100 sink += serialize(node.contentDocument, node.contentDocument instanc
eof XMLDocument); |
| 101 } else { |
| 102 sink += serializeChildren(node, isXML); |
| 103 } |
| 104 |
| 105 if (!_END_TAG_MISSIBLE[tagName] || isXML) |
| 106 sink += '</' + node.nodeName + '>'; |
| 107 return sink; |
| 108 } |
| 109 |
| 110 function applyXSLTransformToCurrentDocument(pi) { |
| 111 var processor = new XSLTProcessor; |
| 112 processor.importStylesheet(pi.styleSheetRootNode_); |
| 113 var transformedDocument = processor.transformToDocument(window.document)
; |
| 114 if (!transformedDocument) |
| 115 return; |
| 116 var content = serialize(transformedDocument, transformedDocument instanc
eof XMLDocument); |
| 117 window.replaceDocument(content, transformedDocument.contentType, transfo
rmedDocument.characterSet); |
| 118 } |
| 119 |
| 120 function findFirstStyleSheet() { |
| 121 for (var child = document.firstChild; child; child = child.nextSibling)
{ |
| 122 if (child.nodeName == 'xml-stylesheet') |
| 123 return child.styleSheetRootNode_ ? child : null; |
| 124 } |
| 125 return null; |
| 126 } |
| 127 |
| 128 function initializeForXSLT(parsing) { |
| 129 window.document.parsing_ = parsing; |
| 130 window.document.addEventListener('DOMContentLoaded', function() { |
| 131 window.document.parsing_ = false; |
| 132 if (window.document.transformSourceDocument_) |
| 133 return; |
| 134 var pi = findFirstStyleSheet(); |
| 135 if (!pi) |
| 136 return; |
| 137 applyXSLTransformToCurrentDocument(pi); |
| 138 }, false); |
| 139 } |
| 140 |
| 141 ProcessingInstructionPrototype.onProcessingInstructionAvailable = function(h
ref, parsing) { |
| 142 if (!window.document.xslStyleSheetInitialized_) |
| 143 initializeForXSLT(parsing); |
| 144 |
| 145 var request = new XMLHttpRequest(); |
| 146 request.pi_ = this; |
| 147 request.onload = function() { |
| 148 var xmldoc = request.responseXML; |
| 149 if (!xmldoc) |
| 150 xmldoc = new DOMParser().parseFromString(request.responseText, '
text/xml'); |
| 151 var regex = new RegExp('#[^/#?]+$'); |
| 152 var match = regex.exec(href); |
| 153 if (match && xmldoc) { |
| 154 this.pi_.styleSheetRootNode_ = xmldoc.getElementById(match[0].su
bstring(1)); |
| 155 } else { |
| 156 this.pi_.styleSheetRootNode_ = xmldoc; |
| 157 } |
| 158 if (window.document.transformSourceDocument_ || window.document.pars
ing_) |
| 159 return; |
| 160 if (findFirstStyleSheet() == this.pi_) |
| 161 applyXSLTransformToCurrentDocument(this.pi_); |
| 162 }; |
| 163 request.open("GET", href, true); |
| 164 request.send(); |
| 165 } |
| 166 }); |
| 167 |
OLD | NEW |