blob: ee14e829ccff405a3c661849963e50245124ab97 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
"use strict";
var tree;
function prepareWebKitXMLViewer()
{
var html = createHTMLElement('html');
var head = createHTMLElement('head');
html.appendChild(head);
var style = createHTMLElement('style');
style.id = 'xml-viewer-style';
head.appendChild(style);
var body = createHTMLElement('body');
html.appendChild(body);
var sourceXML = createHTMLElement('div');
sourceXML.id = 'webkit-xml-viewer-source-xml';
body.appendChild(sourceXML);
var child;
while (child = document.firstChild) {
document.removeChild(child);
if (child.nodeType != Node.DOCUMENT_TYPE_NODE)
sourceXML.appendChild(child);
}
document.appendChild(html);
var header = createHTMLElement('div');
body.appendChild(header);
header.classList.add('header');
var headerSpan = createHTMLElement('span');
header.appendChild(headerSpan);
headerSpan.textContent =
'This XML file does not appear to have any style information ' +
'associated with it. The document tree is shown below.';
header.appendChild(createHTMLElement('br'));
tree = createHTMLElement('div');
body.appendChild(tree);
tree.classList.add('pretty-print');
window.onload = sourceXMLLoaded;
}
function sourceXMLLoaded()
{
var sourceXML = document.getElementById('webkit-xml-viewer-source-xml');
if (!sourceXML)
return; // Stop if some XML tree extension is already processing this
// document
for (var child = sourceXML.firstChild; child; child = child.nextSibling)
processNode(tree, child);
initButtons();
return false;
}
// Tree processing.
function processNode(parentElement, node)
{
switch (node.nodeType) {
case Node.PROCESSING_INSTRUCTION_NODE:
processProcessingInstruction(parentElement, node);
break;
case Node.ELEMENT_NODE:
processElement(parentElement, node);
break;
case Node.COMMENT_NODE:
processComment(parentElement, node);
break;
case Node.TEXT_NODE:
processText(parentElement, node);
break;
case Node.CDATA_SECTION_NODE:
processCDATA(parentElement, node);
break;
default:
// No-op for unsupported node types e.g. Node.DOCUMENT_FRAGMENT_NODE.
}
}
function processElement(parentElement, node)
{
if (!node.firstChild)
processEmptyElement(parentElement, node);
else {
var child = node.firstChild;
if (child.nodeType == Node.TEXT_NODE && !child.nextSibling)
processShortTextOnlyElement(parentElement, node);
else
processComplexElement(parentElement, node);
}
}
function processEmptyElement(parentElement, node)
{
var line = createLine();
line.appendChild(createTag(node, false, true));
parentElement.appendChild(line);
}
function processShortTextOnlyElement(parentElement, node)
{
var line = createLine();
line.appendChild(createTag(node, false, false));
for (var child = node.firstChild; child; child = child.nextSibling)
line.appendChild(createText(child.nodeValue));
line.appendChild(createTag(node, true, false));
parentElement.appendChild(line);
}
function processComplexElement(parentElement, node)
{
var folder = createFolder();
folder.start.appendChild(createTag(node, false, false));
for (var child = node.firstChild; child; child = child.nextSibling)
processNode(folder.openedContent, child);
folder.end.appendChild(createTag(node, true, false));
parentElement.appendChild(folder);
}
function processComment(parentElement, node)
{
var line = createLine();
line.appendChild(createComment('<!-- ' + node.nodeValue + ' -->'));
parentElement.appendChild(line);
}
function processCDATA(parentElement, node)
{
var line = createLine();
line.appendChild(createText('<![CDATA[ ' + node.nodeValue + ' ]]>'));
parentElement.appendChild(line);
}
function processProcessingInstruction(parentElement, node)
{
var line = createLine();
line.appendChild(
createComment('<?' + node.nodeName + ' ' + node.nodeValue + '?>'));
parentElement.appendChild(line);
}
function processText(parentElement, node)
{
parentElement.appendChild(createText(node.nodeValue));
}
// Tree rendering.
function createHTMLElement(elementName)
{
return document.createElementNS('http://www.w3.org/1999/xhtml', elementName)
}
function createFolder()
{
var folder = createHTMLElement('div');
folder.classList.add('folder');
folder.start = createLine();
folder.start.appendChild(createFolderButton());
folder.appendChild(folder.start);
folder.openedContent = createHTMLElement('div');
folder.openedContent.classList.add('opened');
folder.appendChild(folder.openedContent);
// Folded content.
folder.foldedContent = createText('...');
folder.foldedContent.classList.add('folded');
folder.foldedContent.classList.add('hidden');
folder.appendChild(folder.foldedContent);
folder.end = createLine();
folder.appendChild(folder.end);
return folder;
}
function createFolderButton(str) {
var button = createHTMLElement('span');
button.classList.add('folder-button');
button.classList.add('fold');
return button;
}
function createComment(commentString)
{
var comment = createHTMLElement('span');
comment.classList.add('comment');
comment.classList.add('html-comment');
comment.textContent = commentString;
return comment;
}
function createText(value)
{
var text = createHTMLElement('span');
text.textContent = value;
return text;
}
function createLine()
{
var line = createHTMLElement('div');
line.classList.add('line');
return line;
}
function createTag(node, isClosing, isEmpty)
{
var tag = createHTMLElement('span');
tag.classList.add('html-tag');
var stringBeforeAttrs = '<';
if (isClosing)
stringBeforeAttrs += '/';
stringBeforeAttrs += node.nodeName;
var textBeforeAttrs = document.createTextNode(stringBeforeAttrs);
tag.appendChild(textBeforeAttrs);
if (!isClosing) {
for (var i = 0; i < node.attributes.length; i++)
tag.appendChild(createAttribute(node.attributes[i]));
}
var stringAfterAttrs = '';
if (isEmpty)
stringAfterAttrs += '/';
stringAfterAttrs += '>';
var textAfterAttrs = document.createTextNode(stringAfterAttrs);
tag.appendChild(textAfterAttrs);
return tag;
}
function createAttribute(attributeNode)
{
var attribute = createHTMLElement('span');
attribute.classList.add('html-attribute');
var attributeName = createHTMLElement('span');
attributeName.classList.add('html-attribute-name');
attributeName.textContent = attributeNode.name;
var textBefore = document.createTextNode(' ');
var textBetween = document.createTextNode('="');
var attributeValue = createHTMLElement('span');
attributeValue.classList.add('html-attribute-value');
attributeValue.textContent = attributeNode.value;
var textAfter = document.createTextNode('"');
attribute.appendChild(textBefore);
attribute.appendChild(attributeName);
attribute.appendChild(textBetween);
attribute.appendChild(attributeValue);
attribute.appendChild(textAfter);
return attribute;
}
function toggleFunction(sectionId) {
return function() {
var foldedContent = document.querySelector('#' + sectionId + ' > .folded');
var openedContent = document.querySelector('#' + sectionId + ' > .opened');
var folderButton =
document.querySelector('#' + sectionId + ' > .line > .folder-button');
if (foldedContent) {
if (foldedContent.className.includes('hidden'))
foldedContent.className = 'folded';
else
foldedContent.className = 'folded hidden';
}
if (openedContent) {
if (openedContent.className.includes('hidden'))
openedContent.className = 'opened';
else
openedContent.className = 'opened hidden';
}
if (folderButton) {
if (folderButton.className.includes('open'))
folderButton.className = 'folder-button fold';
else
folderButton.className = 'folder-button open';
}
};
}
function initButtons()
{
var sections = document.querySelectorAll('.folder');
for (var i = 0; i < sections.length; i++) {
var sectionId = 'folder' + i;
sections[i].id = sectionId;
var folderButton = sections[i].querySelector('.folder-button');
folderButton.onclick = toggleFunction(sectionId);
folderButton.onmousedown = handleButtonMouseDown;
}
}
function handleButtonMouseDown(e)
{
// To prevent selection on double click
e.preventDefault();
}
prepareWebKitXMLViewer();