Remove namespaced attributes. Fix DOM element tagName parsing. Update HTML so that each scoured file links persist.
This commit is contained in:
parent
fbcbedef37
commit
ac6d4529bd
4 changed files with 127 additions and 36 deletions
|
|
@ -22,16 +22,16 @@
|
||||||
<p id='progressPara' class='hidden'>
|
<p id='progressPara' class='hidden'>
|
||||||
<span id='stage'>Progress</span>: <progress id='progress' max='100'></progress>
|
<span id='stage'>Progress</span>: <progress id='progress' max='100'></progress>
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div id='links' class='hidden'>
|
||||||
<div id='originalSvg' class='hidden'>
|
<div id='originalSvg'>
|
||||||
Original:
|
Original:
|
||||||
<a id='originalLinkText' href='#'>[text]</a>
|
<a id='originalLinkText' target='_blank'>[text]</a>
|
||||||
<a id='originalLinkSvg' href='#'>[svg]</a>
|
<a id='originalLinkSvg' target='_blank'>[svg]</a>
|
||||||
</div>
|
</div>
|
||||||
<div id='scouredSvg' class='hidden'>
|
<div id='scouredSvg'>
|
||||||
Scoured:
|
Scoured:
|
||||||
<a id='scouredLinkText' href='#'>[text]</a>
|
<a id='scouredLinkText' target='_blank'>[text]</a>
|
||||||
<a id='scouredLinkSvg' href='#'>[svg]</a>
|
<a id='scouredLinkSvg' target='_blank'>[svg]</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id='status' class='hidden'></div>
|
<div id='status' class='hidden'></div>
|
||||||
|
|
@ -44,19 +44,6 @@
|
||||||
var originalSvg;
|
var originalSvg;
|
||||||
var scouredSvg;
|
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) {
|
var handleMessage = function(evt) {
|
||||||
if (typeof evt.data == 'string') {
|
if (typeof evt.data == 'string') {
|
||||||
var p = document.createElement('p');
|
var p = document.createElement('p');
|
||||||
|
|
@ -73,13 +60,28 @@
|
||||||
if (evt.data.progress) {
|
if (evt.data.progress) {
|
||||||
handleProgress(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) {
|
if (evt.data.scouredSvg) {
|
||||||
document.getElementById('scouredSvg').className = '';
|
|
||||||
scouredSvg = evt.data.scouredSvg;
|
scouredSvg = evt.data.scouredSvg;
|
||||||
handleMessage({
|
handleMessage({
|
||||||
data: 'Scoured SVG came out to be ' +
|
data: 'Scoured SVG came out to be ' +
|
||||||
evt.data.scouredSvg.length + ' bytes'
|
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) {
|
var getFile = function(evt) {
|
||||||
stageSpan.innerHTML = 'Loading';
|
stageSpan.innerHTML = 'Loading';
|
||||||
var showElems = ['progressPara', 'status', 'originalSvg'];
|
var showElems = ['progressPara', 'status'];
|
||||||
for (var i in showElems) {
|
for (var i in showElems) {
|
||||||
document.getElementById(showElems[i]).className = '';
|
document.getElementById(showElems[i]).className = '';
|
||||||
}
|
}
|
||||||
|
|
@ -102,6 +104,8 @@
|
||||||
// TODO: Use addEventListener when WebKit supports it
|
// TODO: Use addEventListener when WebKit supports it
|
||||||
// https://bugs.webkit.org/show_bug.cgi?id=42723
|
// https://bugs.webkit.org/show_bug.cgi?id=42723
|
||||||
fr.onload = function(evt) {
|
fr.onload = function(evt) {
|
||||||
|
handleMessage({data:
|
||||||
|
'-------------------------------------------------------------------------------'});
|
||||||
handleMessage({data:'Loaded \'' + theFile.name + '\'' + ' (' + theFile.size + ' bytes)'});
|
handleMessage({data:'Loaded \'' + theFile.name + '\'' + ' (' + theFile.size + ' bytes)'});
|
||||||
var worker = new Worker('scour.js');
|
var worker = new Worker('scour.js');
|
||||||
worker.addEventListener('message', handleMessage);
|
worker.addEventListener('message', handleMessage);
|
||||||
|
|
|
||||||
51
lite/pdom.js
51
lite/pdom.js
|
|
@ -109,10 +109,11 @@ pdom.NodeList.prototype.item = function(index) {
|
||||||
/**
|
/**
|
||||||
* @param {Object.<string, pdom.Node>} nodeMap An object containing the
|
* @param {Object.<string, pdom.Node>} nodeMap An object containing the
|
||||||
* attribute name-Node pairs.
|
* attribute name-Node pairs.
|
||||||
|
* @param {pdom.Node} opt_refNode An optional reference node.
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
pdom.NamedNodeMap = function(nodeMap) {
|
pdom.NamedNodeMap = function(nodeMap, opt_refNode) {
|
||||||
this.setNodeMapInternal(nodeMap);
|
this.setNodeMapInternal(nodeMap, opt_refNode);
|
||||||
this.__defineGetter__('length', function() { return this.attrs_.length });
|
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).
|
* Sets the internal node map (and updates the array).
|
||||||
* @param {Object.<string, pdom.Node>} The node map.
|
* @param {Object.<string, pdom.Node>} 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.nodeMap_ = {};
|
||||||
this.attrs_ = [];
|
this.attrs_ = [];
|
||||||
for (var name in nodeMap) {
|
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.attrs_.push(attr);
|
||||||
this.nodeMap_[name] = 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} name The name of the attribute.
|
||||||
* @param {string} value The value of the attribute.
|
* @param {string} value The value of the attribute.
|
||||||
|
* @param {stirng} opt_namespaceURI Optional namespace URI.
|
||||||
* @constructor
|
* @constructor
|
||||||
* @extends {pdom.Attr}
|
* @extends {pdom.Attr}
|
||||||
*/
|
*/
|
||||||
pdom.Attr = function(name, value) {
|
pdom.Attr = function(name, value, opt_namespaceURI) {
|
||||||
pdom.base(this, null);
|
pdom.base(this, null);
|
||||||
|
|
||||||
this.__defineGetter__('nodeType', function() {
|
this.__defineGetter__('nodeType', function() {
|
||||||
return pdom.Node.ATTRIBUTE_NODE;
|
return pdom.Node.ATTRIBUTE_NODE;
|
||||||
});
|
});
|
||||||
this.__defineGetter__('name', function() { return name });
|
this.__defineGetter__('name', function() { return name });
|
||||||
|
this.__defineGetter__('namespaceURI', function() { return opt_namespaceURI });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
|
@ -375,7 +399,7 @@ pdom.Element = function(tagName, opt_parentNode, opt_attrs) {
|
||||||
|
|
||||||
this.__defineGetter__('attributes', function() {
|
this.__defineGetter__('attributes', function() {
|
||||||
if (!this.attributeMap_) {
|
if (!this.attributeMap_) {
|
||||||
this.attributeMap_ = new pdom.NamedNodeMap(this.attributes_);
|
this.attributeMap_ = new pdom.NamedNodeMap(this.attributes_, this);
|
||||||
}
|
}
|
||||||
return this.attributeMap_;
|
return this.attributeMap_;
|
||||||
});
|
});
|
||||||
|
|
@ -453,7 +477,7 @@ pdom.Element.prototype.getAttribute = function(attrName) {
|
||||||
pdom.Element.prototype.setAttribute = function(name, value) {
|
pdom.Element.prototype.setAttribute = function(name, value) {
|
||||||
this.attributes_[name] = value;
|
this.attributes_[name] = value;
|
||||||
if (this.attributeMap_) {
|
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) {
|
pdom.Element.prototype.removeAttribute = function(name) {
|
||||||
delete this.attributes_[name];
|
delete this.attributes_[name];
|
||||||
if (this.attributeMap_) {
|
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) {
|
if (endDocType == -1) {
|
||||||
throw 'Could not find the end of the DOCTYPE (>)';
|
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.currentNode.childNodes_.push(newDocType);
|
||||||
parsingContext.offset = endDocType + 1;
|
parsingContext.offset = endDocType + 1;
|
||||||
return newDocType;
|
return newDocType;
|
||||||
|
|
@ -706,9 +730,12 @@ pdom.parse.parseOneNode_ = function(parsingContext) {
|
||||||
|
|
||||||
var attrs = {};
|
var attrs = {};
|
||||||
|
|
||||||
// TODO: This should be whitespace, not space.
|
// Find if whitespace occurs before the end of the start tag.
|
||||||
var tagNameIndex = xmlText.indexOf(' ', i + 1);
|
var wsMatches = xmlText.substring(i + 1).match(/\s+/);
|
||||||
if (tagNameIndex == -1 || tagNameIndex > endStartTagIndex) {
|
var tagNameIndex = wsMatches && wsMatches.length > 0 ?
|
||||||
|
wsMatches.index + i + 1 :
|
||||||
|
endStartTagIndex;
|
||||||
|
if (tagNameIndex > endStartTagIndex) {
|
||||||
tagNameIndex = endStartTagIndex;
|
tagNameIndex = endStartTagIndex;
|
||||||
} else {
|
} else {
|
||||||
// Find all attributes and record them.
|
// Find all attributes and record them.
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
function testParseSimpleGetAttribute() {
|
function testParseSimpleGetAttribute() {
|
||||||
var doc = new pdom.DOMParser().parseFromString(
|
var doc = new pdom.DOMParser().parseFromString(
|
||||||
'<?xml version="1.0"?><simple bar="foo" foo=\'bar\'' +
|
'<simple bar="foo" foo=\'bar\'' +
|
||||||
' baz = " blah blah "' +
|
' baz = " blah blah "' +
|
||||||
'/>');
|
'/>');
|
||||||
|
|
||||||
|
|
@ -43,6 +43,15 @@
|
||||||
muther.assert(elem.getAttribute('foo') == 'bar', 'foo attribute not correct');
|
muther.assert(elem.getAttribute('foo') == 'bar', 'foo attribute not correct');
|
||||||
muther.assert(elem.getAttribute('baz') == ' blah blah ', 'baz attribute not correct');
|
muther.assert(elem.getAttribute('baz') == ' blah blah ', 'baz attribute not correct');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
function testParseTagNameWithEOL() {
|
||||||
|
var doc = new pdom.DOMParser().parseFromString('<parent\n/>');
|
||||||
|
|
||||||
|
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() {
|
function testNodeTypes() {
|
||||||
var doc = new pdom.DOMParser().parseFromString('<simple foo="bar"><!-- Comment -->Text</simple>');
|
var doc = new pdom.DOMParser().parseFromString('<simple foo="bar"><!-- Comment -->Text</simple>');
|
||||||
|
|
@ -111,6 +120,20 @@
|
||||||
muther.assert(grandChild.namespaceURI === "http://bar/",
|
muther.assert(grandChild.namespaceURI === "http://bar/",
|
||||||
'prefixed namespaceURI did not work');
|
'prefixed namespaceURI did not work');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
function testNamespacedAttributes() {
|
||||||
|
var NS_BAR = 'http://bar/';
|
||||||
|
var doc = new pdom.DOMParser().parseFromString(
|
||||||
|
'<parent xmlns="http://foo/" xmlns:bar="http://bar/" bar:foo="baz">' +
|
||||||
|
'<child bar:baz="blah"/></parent>');
|
||||||
|
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() {
|
function testTagName() {
|
||||||
var doc = new pdom.DOMParser().parseFromString('<simple/>');
|
var doc = new pdom.DOMParser().parseFromString('<simple/>');
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ var removeNamespacedElements = function(node, namespaces) {
|
||||||
var child = node.childNodes.item(i);
|
var child = node.childNodes.item(i);
|
||||||
if (namespaces.indexOf(child.namespaceURI) != -1) {
|
if (namespaces.indexOf(child.namespaceURI) != -1) {
|
||||||
childrenToRemove.push(child);
|
childrenToRemove.push(child);
|
||||||
|
postMessage({update: '.'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,6 +64,35 @@ var removeNamespacedElements = function(node, namespaces) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {pdom.Node|Node} node The parent node.
|
||||||
|
* @param {Array.<string>} 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 {string} in_string The SVG document as a string.
|
||||||
* @param {object} opt_options An optional set of options.
|
* @param {object} opt_options An optional set of options.
|
||||||
|
|
@ -76,8 +106,15 @@ var scourString = function(in_string, opt_options) {
|
||||||
|
|
||||||
// Remove editor stuff.
|
// Remove editor stuff.
|
||||||
if (!options.keep_editor_data) {
|
if (!options.keep_editor_data) {
|
||||||
|
postMessage({message: 'Removing namespaced elements '});
|
||||||
removeNamespacedElements(doc.documentElement, unwanted_ns);
|
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);
|
return new pdom.XMLSerializer().serializeToString(doc);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue