+
-
@@ -44,19 +44,6 @@
var originalSvg;
var scouredSvg;
- document.getElementById('originalLinkText').onclick = function(evt) {
- window.open('data:text/plain;base64,' + window.btoa(originalSvg));
- };
- document.getElementById('originalLinkSvg').onclick = function(evt) {
- window.open('data:image/svg+xml;base64,' + window.btoa(originalSvg));
- };
- document.getElementById('scouredLinkText').onclick = function(evt) {
- window.open('data:text/plain;base64,' + window.btoa(scouredSvg));
- };
- document.getElementById('scouredLinkSvg').onclick = function(evt) {
- window.open('data:image/svg+xml;base64,' + window.btoa(scouredSvg));
- };
-
var handleMessage = function(evt) {
if (typeof evt.data == 'string') {
var p = document.createElement('p');
@@ -73,13 +60,28 @@
if (evt.data.progress) {
handleProgress(evt.data.progress);
}
+ if (evt.data.update) {
+ var status = document.getElementById('status').firstChild;
+ status.innerHTML = status.innerHTML + evt.data.update;
+ }
if (evt.data.scouredSvg) {
- document.getElementById('scouredSvg').className = '';
scouredSvg = evt.data.scouredSvg;
handleMessage({
data: 'Scoured SVG came out to be ' +
evt.data.scouredSvg.length + ' bytes'
});
+
+ var status = document.getElementById('status');
+ var links = document.getElementById('links');
+ document.getElementById('originalLinkText').setAttribute('href',
+ 'data:text/plain;base64,' + window.btoa(originalSvg));
+ document.getElementById('originalLinkSvg').setAttribute('href',
+ 'data:image/svg+xml;base64,' + window.btoa(originalSvg));
+ document.getElementById('scouredLinkText').setAttribute('href',
+ 'data:text/plain;base64,' + window.btoa(scouredSvg));
+ document.getElementById('scouredLinkSvg').setAttribute('href',
+ 'data:image/svg+xml;base64,' + window.btoa(scouredSvg));
+ status.innerHTML = links.innerHTML + status.innerHTML;
}
}
};
@@ -89,7 +91,7 @@
};
var getFile = function(evt) {
stageSpan.innerHTML = 'Loading';
- var showElems = ['progressPara', 'status', 'originalSvg'];
+ var showElems = ['progressPara', 'status'];
for (var i in showElems) {
document.getElementById(showElems[i]).className = '';
}
@@ -102,6 +104,8 @@
// TODO: Use addEventListener when WebKit supports it
// https://bugs.webkit.org/show_bug.cgi?id=42723
fr.onload = function(evt) {
+ handleMessage({data:
+ '-------------------------------------------------------------------------------'});
handleMessage({data:'Loaded \'' + theFile.name + '\'' + ' (' + theFile.size + ' bytes)'});
var worker = new Worker('scour.js');
worker.addEventListener('message', handleMessage);
diff --git a/lite/pdom.js b/lite/pdom.js
index c4b9d76..5d6a947 100644
--- a/lite/pdom.js
+++ b/lite/pdom.js
@@ -109,10 +109,11 @@ pdom.NodeList.prototype.item = function(index) {
/**
* @param {Object.
} nodeMap An object containing the
* attribute name-Node pairs.
+ * @param {pdom.Node} opt_refNode An optional reference node.
* @constructor
*/
-pdom.NamedNodeMap = function(nodeMap) {
- this.setNodeMapInternal(nodeMap);
+pdom.NamedNodeMap = function(nodeMap, opt_refNode) {
+ this.setNodeMapInternal(nodeMap, opt_refNode);
this.__defineGetter__('length', function() { return this.attrs_.length });
};
@@ -136,12 +137,33 @@ pdom.NamedNodeMap.prototype.nodeMap_ = {};
/**
* Sets the internal node map (and updates the array).
* @param {Object.} The node map.
+ * @param {pdom.Node} opt_refNode The optional reference node for namespace prefix checking.
*/
-pdom.NamedNodeMap.prototype.setNodeMapInternal = function(nodeMap) {
+pdom.NamedNodeMap.prototype.setNodeMapInternal = function(nodeMap, opt_refNode) {
+ var nsPrefixMap = {};
+ if (opt_refNode) {
+ var node = opt_refNode;
+ while (node) {
+ for (var prefix in node.nsPrefixMapInternal) {
+ nsPrefixMap[prefix] = node.nsPrefixMapInternal[prefix];
+ }
+ node = node.parentNode;
+ }
+ }
this.nodeMap_ = {};
this.attrs_ = [];
for (var name in nodeMap) {
- var attr = new pdom.Attr(name, nodeMap[name]);
+ // If the attribute name includes a colon, resolve the namespace prefix.
+ var colonIndex = name.indexOf(':');
+ var namespaceURI = null;
+ if (colonIndex != -1) {
+ var prefix = name.substring(0, colonIndex);
+ var uri = nsPrefixMap[prefix];
+ if (uri) {
+ namespaceURI = uri;
+ }
+ }
+ var attr = new pdom.Attr(name, nodeMap[name], namespaceURI);
this.attrs_.push(attr);
this.nodeMap_[name] = attr;
}
@@ -334,16 +356,18 @@ pdom.inherits(pdom.DocumentType, pdom.Node);
*
* @param {string} name The name of the attribute.
* @param {string} value The value of the attribute.
+ * @param {stirng} opt_namespaceURI Optional namespace URI.
* @constructor
* @extends {pdom.Attr}
*/
-pdom.Attr = function(name, value) {
+pdom.Attr = function(name, value, opt_namespaceURI) {
pdom.base(this, null);
this.__defineGetter__('nodeType', function() {
return pdom.Node.ATTRIBUTE_NODE;
});
this.__defineGetter__('name', function() { return name });
+ this.__defineGetter__('namespaceURI', function() { return opt_namespaceURI });
/**
* @type {string}
@@ -375,7 +399,7 @@ pdom.Element = function(tagName, opt_parentNode, opt_attrs) {
this.__defineGetter__('attributes', function() {
if (!this.attributeMap_) {
- this.attributeMap_ = new pdom.NamedNodeMap(this.attributes_);
+ this.attributeMap_ = new pdom.NamedNodeMap(this.attributes_, this);
}
return this.attributeMap_;
});
@@ -453,7 +477,7 @@ pdom.Element.prototype.getAttribute = function(attrName) {
pdom.Element.prototype.setAttribute = function(name, value) {
this.attributes_[name] = value;
if (this.attributeMap_) {
- this.attributeMap_.setNodeMapInternal(this.attributes_);
+ this.attributeMap_.setNodeMapInternal(this.attributes_, this);
}
};
@@ -464,7 +488,7 @@ pdom.Element.prototype.setAttribute = function(name, value) {
pdom.Element.prototype.removeAttribute = function(name) {
delete this.attributes_[name];
if (this.attributeMap_) {
- this.attributeMap_.setNodeMapInternal(this.attributes_);
+ this.attributeMap_.setNodeMapInternal(this.attributes_, this);
}
};
@@ -658,7 +682,7 @@ pdom.parse.parseOneNode_ = function(parsingContext) {
if (endDocType == -1) {
throw 'Could not find the end of the DOCTYPE (>)';
}
- var newDocType = new pdom.DocType();
+ var newDocType = new pdom.DocumentType();
parsingContext.currentNode.childNodes_.push(newDocType);
parsingContext.offset = endDocType + 1;
return newDocType;
@@ -706,9 +730,12 @@ pdom.parse.parseOneNode_ = function(parsingContext) {
var attrs = {};
- // TODO: This should be whitespace, not space.
- var tagNameIndex = xmlText.indexOf(' ', i + 1);
- if (tagNameIndex == -1 || tagNameIndex > endStartTagIndex) {
+ // Find if whitespace occurs before the end of the start tag.
+ var wsMatches = xmlText.substring(i + 1).match(/\s+/);
+ var tagNameIndex = wsMatches && wsMatches.length > 0 ?
+ wsMatches.index + i + 1 :
+ endStartTagIndex;
+ if (tagNameIndex > endStartTagIndex) {
tagNameIndex = endStartTagIndex;
} else {
// Find all attributes and record them.
diff --git a/lite/pdom_test.html b/lite/pdom_test.html
index 45ca74b..8104955 100644
--- a/lite/pdom_test.html
+++ b/lite/pdom_test.html
@@ -31,7 +31,7 @@
function testParseSimpleGetAttribute() {
var doc = new pdom.DOMParser().parseFromString(
- '');
@@ -43,6 +43,15 @@
muther.assert(elem.getAttribute('foo') == 'bar', 'foo attribute not correct');
muther.assert(elem.getAttribute('baz') == ' blah blah ', 'baz attribute not correct');
},
+
+ function testParseTagNameWithEOL() {
+ var doc = new pdom.DOMParser().parseFromString('');
+
+ var parent = doc.documentElement;
+ muther.assert(parent, 'Could not parse documentElement');
+ muther.assert(parent.tagName == 'parent', 'Did not parse the parent tagName: \'' +
+ parent.tagName + '\'');
+ },
function testNodeTypes() {
var doc = new pdom.DOMParser().parseFromString('Text');
@@ -111,6 +120,20 @@
muther.assert(grandChild.namespaceURI === "http://bar/",
'prefixed namespaceURI did not work');
},
+
+ function testNamespacedAttributes() {
+ var NS_BAR = 'http://bar/';
+ var doc = new pdom.DOMParser().parseFromString(
+ '' +
+ '');
+ var parent = doc.documentElement;
+ var child = parent.firstChild;
+
+ muther.assert(parent.attributes.getNamedItem('bar:foo').namespaceURI == NS_BAR,
+ 'bar: attribute on parent does not have the proper namespaceURI');
+ muther.assert(child.attributes.item(0).namespaceURI == NS_BAR,
+ 'bar: attribute on child does not have the proper namespaceURI');
+ },
function testTagName() {
var doc = new pdom.DOMParser().parseFromString('');
diff --git a/lite/scour.js b/lite/scour.js
index 48c13d1..f540270 100644
--- a/lite/scour.js
+++ b/lite/scour.js
@@ -48,6 +48,7 @@ var removeNamespacedElements = function(node, namespaces) {
var child = node.childNodes.item(i);
if (namespaces.indexOf(child.namespaceURI) != -1) {
childrenToRemove.push(child);
+ postMessage({update: '.'});
}
}
@@ -63,6 +64,35 @@ var removeNamespacedElements = function(node, namespaces) {
};
+/**
+ * @param {pdom.Node|Node} node The parent node.
+ * @param {Array.} namespaces An array of namespace URIs.
+ */
+var removeNamespacedAttributes = function(node, namespaces) {
+ if (node.nodeType == 1) {
+ // Remove all namespace'd attributes from this element.
+ var attrsToRemove = [];
+ for (var i = 0; i < node.attributes.length; ++i) {
+ var attr = node.attributes.item(i);
+ if (namespaces.indexOf(attr.namespaceURI) != -1 ||
+ (namespaces.indexOf(attr.value) != -1 && attr.name.indexOf('xmlns:') == 0)) {
+ attrsToRemove.push(attr);
+ postMessage({update: '.'});
+ }
+ }
+
+ for (var i = 0; i < attrsToRemove.length; ++i) {
+ node.removeAttribute(attrsToRemove[i].name);
+ }
+
+ // Now recurse for children.
+ for (var i = 0; i < node.childNodes.length; ++i) {
+ removeNamespacedAttributes(node.childNodes.item(i), namespaces);
+ }
+ }
+};
+
+
/**
* @param {string} in_string The SVG document as a string.
* @param {object} opt_options An optional set of options.
@@ -76,8 +106,15 @@ var scourString = function(in_string, opt_options) {
// Remove editor stuff.
if (!options.keep_editor_data) {
+ postMessage({message: 'Removing namespaced elements '});
removeNamespacedElements(doc.documentElement, unwanted_ns);
- postMessage({message: 'Removed namespaced elements'});
+ postMessage({update: ' done!'});
+ postMessage({progress: {loaded: 45, total: 100}});
+
+ postMessage({message: 'Removing namespaced attributes '});
+ removeNamespacedAttributes(doc.documentElement, unwanted_ns);
+ postMessage({update: ' done!'});
+ postMessage({progress: {loaded: 90, total: 100}});
}
return new pdom.XMLSerializer().serializeToString(doc);