Skip to content

Commit

Permalink
Merge branch 'master' of http://github.com/tmpvar/jsdom
Browse files Browse the repository at this point in the history
Conflicts:
	lib/jsdom/level2/events.js
  • Loading branch information
Felix Gnass committed Oct 28, 2010
2 parents 527d2cd + 4f2191d commit f91124d
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 45 deletions.
71 changes: 50 additions & 21 deletions lib/jsdom/browser/htmlencoding.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,32 @@ var htmlentities = function(string, quote_style) {

string = string || "";

var hash_map = {}, symbol = '', tmp_str = '', entity = '';
var hash_map = {}, symbol, tmp_str = '', entity = '';
tmp_str = string.toString();

if (false === (hash_map = get_html_translation_table('HTML_ENTITIES', quote_style))) {

if (false === (hash_map = get_html_translation_table('HTML_SPECIALCHARS', quote_style))) {
return false;
}

hash_map["'"] = ''';
delete hash_map["&"];
tmp_str = tmp_str.split("&").join('&');

tmp_str = tmp_str.split(''').join("'");
tmp_str = tmp_str.split('"').join('"');
tmp_str = tmp_str.split(''').join("'");
tmp_str = tmp_str.split('"').join('"');

// amended by ejones - get_html_translation_table no longer translates
// char codes by default

//hash_map["'"] = ''';
delete hash_map['38']; // &
tmp_str = tmp_str.split('&').join('&');
for (symbol in hash_map) {
entity = hash_map[symbol];
tmp_str = tmp_str.split(symbol).join(entity);
tmp_str = tmp_str
.split(String.fromCharCode(symbol))
.join(hash_map[symbol]);
}

return tmp_str;
Expand All @@ -166,23 +180,33 @@ var html_entity_decode = function(string, quote_style) {

string = string || "";

var hash_map = {}, symbol = '', tmp_str = '', entity = '';
var hash_map = {}, symbol, tmp_str = '',
entity = '', entity_to_char_code = {};
tmp_str = string.toString();

if (false === (hash_map = get_html_translation_table('HTML_ENTITIES', quote_style))) {
return false;
}

// fix & problem
// http://phpjs.org/functions/get_html_translation_table:416#comment_97660
delete(hash_map['&']);
hash_map['&'] = '&';


// amended by ejones - more flexible recognition of entities
for (symbol in hash_map) {
entity = hash_map[symbol];
tmp_str = tmp_str.split(entity).join(symbol);
entity_to_char_code[hash_map[symbol]] = symbol;
}
tmp_str = tmp_str.split(''').join("'");

tmp_str = tmp_str.replace(/&([#a-z0-9]+);/gi, function( ent, ename ) {
var char = entity_to_char_code[ent];
if (char == null && ename === 'apos') char = 39;
if (char == null && ename[0] === '#') {
if (ename[1].toLowerCase() === 'x') {
char = parseInt(ename.substring(2), 16);
} else {
char = parseInt(ename.substring(1), 10);
};
if (isNaN(char)) char = null;
};
return char != null ? String.fromCharCode(char) : ent;
});

return tmp_str;
};
Expand Down Expand Up @@ -221,7 +245,7 @@ var get_html_translation_table = function(table, quote_style) {
constMappingQuoteStyle[3] = 'ENT_QUOTES';

useTable = !isNaN(table) ? constMappingTable[table] : table ? table.toUpperCase() : 'HTML_SPECIALCHARS';
useQuoteStyle = !isNaN(quote_style) ? constMappingQuoteStyle[quote_style] : quote_style ? quote_style.toUpperCase() : 'ENT_COMPAT';
useQuoteStyle = !isNaN(quote_style) ? constMappingQuoteStyle[quote_style] : quote_style ? quote_style.toUpperCase() : 'ENT_QUOTES';

if (useTable !== 'HTML_SPECIALCHARS' && useTable !== 'HTML_ENTITIES') {
throw new Error("Table: "+useTable+' not supported');
Expand Down Expand Up @@ -338,13 +362,18 @@ var get_html_translation_table = function(table, quote_style) {
entities['62'] = '>';


// ascii decimals to real symbols
for (decimal in entities) {
symbol = String.fromCharCode(decimal);
hash_map[symbol] = entities[decimal];
}

// removed by ejones - translation now done in encoding/decoding

//// ascii decimals to real symbols
//for (decimal in entities) {
// symbol = String.fromCharCode(decimal);
// hash_map[symbol] = entities[decimal];
//}

//return hash_map;

return hash_map;
return entities;
};

/* }}} */
Expand Down
78 changes: 72 additions & 6 deletions lib/jsdom/browser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,11 @@ var browserAugmentation = exports.browserAugmentation = function(dom, options) {
});

dom.Document.prototype.__defineGetter__('outerHTML', function() {
return domToHtml(this.documentElement);
var html = domToHtml(this.documentElement);
if (this.doctype) {
html = this.doctype.toString() + '\n' + html;
}
return html;
});

dom.Document.prototype._elementBuilders['script'] = function(doc, name) {
Expand Down Expand Up @@ -408,6 +412,19 @@ var browserAugmentation = exports.browserAugmentation = function(dom, options) {
dom.Element.prototype.__defineGetter__('innerHTML', function() {
return domToHtml(this.childNodes, true);
});
dom.Element.prototype.__defineSetter__('doctype', function() {
throw new core.DOMException(NO_MODIFICATION_ALLOWED_ERR);
});
dom.Element.prototype.__defineGetter__('doctype', function() {
var r = null;
if (this.nodeName == '#document') {
if (this._doctype) {
r = this._doctype;
}
}
return r;
});

dom.Element.prototype.__defineSetter__('innerHTML', function(html) {
//Check for lib first

Expand All @@ -421,11 +438,64 @@ var browserAugmentation = exports.browserAugmentation = function(dom, options) {
this.childNodes[i].parentNode.removeChild(this.childNodes[i]);
}
}

if (this.nodeName === '#document') {
parseDocType(this, html);
}
var nodes = htmltodom.appendHtmlToElement(html, this);
return html;
});

var DOC_HTML5 = /<!doctype html>/is,
DOC_TYPE = /<!DOCTYPE (\w.*)">/is;

var parseDocType = function(doc, html) {
var publicID = '',
systemID = '',
fullDT = '',
name = 'HTML',
set = true,
html5DT = html.match(DOC_HTML5),
dt = html.match(DOC_TYPE);

//Default, No doctype === null
doc._doctype = null;

if (html5DT && html5DT[0]) { //Handle the HTML shorty doctype
fullDT = html5DT[0];

} else if (dt && dt[1]) { //Parse the doctype
fullDT = dt[0];
dt = dt[1].split(' "');
var _id1 = dt.pop().replace(/"/g, ''),
_id2 = dt.pop().replace(/"/g, '');

if (_id1.indexOf('-//') !== -1) {
publicID = _id1;
}
if (_id2.indexOf('-//') !== -1) {
publicID = _id2;
}
if (_id1.indexOf('://') !== -1) {
systemID = _id1;
}
if (_id2.indexOf('://') !== -1) {
systemID = _id2;
}
if (dt.length) {
dt = dt[0].split(' ');
name = dt[0].toUpperCase();
}
} else {
//No DocType found
return;
}
doc._doctype = new dom.DOMImplementation().createDocumentType(name, publicID, systemID);
doc._doctype._ownerDocument = doc;
doc._doctype._fullDT = fullDT;
doc._doctype.toString = function() {
return this._fullDT;
};
}

dom.Document.prototype.__defineGetter__("body", function() {
return this.getElementsByTagName("body").item(0);
Expand Down Expand Up @@ -692,8 +762,6 @@ var browserAugmentation = exports.browserAugmentation = function(dom, options) {
dom.Element.prototype.__defineGetter__('textContent', function() {
var stripHTML = /<\S[^><]*>/g;
var out = this.innerHTML;
//Encode all the spaces
out = out.replace(/&nbsp;/g, ' ');
//Remove all the HTML
out = out.replace(stripHTML, '');
//Now decode the encoded text content
Expand All @@ -703,8 +771,6 @@ var browserAugmentation = exports.browserAugmentation = function(dom, options) {
dom.Element.prototype.__defineSetter__('textContent', function(txt) {
//Un encode all the entities
txt = HTMLEncode(txt);
//Now replace all the spaces with non-breaking spaces
txt = txt.replace(/ {2}/g, '&nbsp;&nbsp;');
//Set the content
this.innerHTML = txt;
return txt;
Expand Down
34 changes: 17 additions & 17 deletions lib/jsdom/level2/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,27 +285,27 @@ core.Node.prototype.__proto__ = events.EventTarget.prototype;

// Wrap the level-1 implementation of appendChild() to dispatch a DOMNodeInserted event
(function(level1) {
core.Node.prototype.appendChild = function(newChild) {
var ret = level1.call(this, newChild);
if (this.nodeType == 1 && this.ownerDocument) {
var ev = this.ownerDocument.createEvent("MutationEvents");
ev.initMutationEvent("DOMNodeInserted", true, false, this, null, null, null, null);
newChild.dispatchEvent(ev);
}
return ret;
};
core.Node.prototype.appendChild = function(newChild) {
var ret = level1.call(this, newChild);
if (this.nodeType == 1 && this.ownerDocument) {
var ev = this.ownerDocument.createEvent("MutationEvents");
ev.initMutationEvent("DOMNodeInserted", true, false, this, null, null, null, null);
newChild.dispatchEvent(ev);
}
return ret;
};
})(core.Node.prototype.appendChild);

// Wrap the level-1 implementation of removeChild() to dispatch a DOMNodeRemoved event
(function(level1) {
core.Node.prototype.removeChild = function(oldChild) {
if (this.ownerDocument) {
var ev = this.ownerDocument.createEvent("MutationEvents");
ev.initMutationEvent("DOMNodeRemoved", true, false, this, null, null, null, null);
oldChild.dispatchEvent(ev);
}
return level1.call(this, oldChild);
};
core.Node.prototype.removeChild = function(oldChild) {
if (this.ownerDocument) {
var ev = this.ownerDocument.createEvent("MutationEvents");
ev.initMutationEvent("DOMNodeRemoved", true, false, this, null, null, null, null);
oldChild.dispatchEvent(ev);
}
return level1.call(this, oldChild);
};
})(core.Node.prototype.removeChild);

// Wrap the level-1 implementation to dispatch a DOMAttrModified event
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jsdom",
"version": "0.1.18",
"version": "0.1.19",
"description": "CommonJS implementation of the DOM intended to be platform independent and as minimal/light as possible while completely adhering to the w3c DOM specifications.",
"keywords": [
"dom",
Expand Down

0 comments on commit f91124d

Please sign in to comment.