Comparing version 0.0.1-beta4 to 0.0.1-beta5
{ | ||
"name": "browser-x", | ||
"version": "0.0.1-beta4", | ||
"version": "0.0.1-beta5", | ||
"description": "A partial implementation of the W3C DOM API on top of an HTML5 parser and serializer.", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/aui/browser-x", |
# browser-x | ||
browser-x 一个基于 NodeJS 实现的“浏览器”,它实现了浏览器的精华 API,适用于文档或样式节点分析: | ||
browser-x 是一个基于 NodeJS 实现的轻量级“浏览器”,它的目标是高效的实现 DOM 中最核心的特性,以便开发者能够在 NodeJS 中使用 W3C 标准方法来操作文档与样式。 | ||
* 使用 CSS3 选择器来操作 DOM | ||
* 分析 CSS 在文档中的应用情况 | ||
## 安装 | ||
@@ -18,3 +15,3 @@ | ||
返回:Promise | ||
返回:`Promise` | ||
@@ -161,2 +158,3 @@ ``` javascript | ||
- [outerHTML](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/outerHTML) | ||
- [attributes](https://developer.mozilla.org/zh-CN/docs/Web/API/Node.attributes) | ||
- [hasAttribute()](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/hasAttribute) | ||
@@ -169,7 +167,6 @@ - [getAttribute()](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getAttribute) | ||
* HTMLElement | ||
- [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) | ||
- [style](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/style) | ||
* Node | ||
- [nodeName](https://developer.mozilla.org/zh-CN/docs/Web/API/Node.nodeName) | ||
- [nodeType](https://developer.mozilla.org/zh-CN/docs/Web/API/Node.nodeType) | ||
- [attributes](https://developer.mozilla.org/zh-CN/docs/Web/API/Node.attributes) | ||
- [childNodes](https://developer.mozilla.org/zh-CN/docs/Web/API/Node.childNodes) | ||
@@ -187,3 +184,3 @@ - [parentNode](https://developer.mozilla.org/zh-CN/docs/Web/API/Node.parentNode) | ||
1. 不支持 XML 文档解析 | ||
2. 所有的 DOM 属性均为只读(*计划在下一版本支持*) | ||
2. 所有的 DOM 属性均为只读(*计划在下一版本支持写入*) | ||
3. window.getComputedStyle() 仅能获取元素或伪元素在 CSS 中定义的原始值或继承属性,但没有进行计算输出(例如 em \> px) | ||
@@ -197,9 +194,7 @@ 4. document.styleSheets 在浏览器中无法跨域访问 CSSOM,browser-x 没有做此限制 | ||
1. 爬虫程序 | ||
1. 高效的爬虫程序,使用 CSS 选择器来收集内容 | ||
2. 分析元素的样式使用情况,例如和 CSS 相关的开发工具 | ||
如果需要更多的 DOM 特性,例如跑基于 DOM 的测试脚本、甚至载入 jQuery 等,那么 [jsdom](https://github.com/tmpvar/jsdom) 这个项目可能会更适合你(它唯一没有做好的是样式解析)。 | ||
例如:WebFont 压缩工具——[font-spider](https://github.com/aui/font-spider) | ||
### 它们在使用 browser-x | ||
1. [font-spider](https://github.com/aui/font-spider) | ||
如果需要更多的 DOM 特性,例如跑基于 DOM 的测试脚本、甚至载入 jQuery 等,那么 [jsdom](https://github.com/tmpvar/jsdom) 这个项目可能会更适合你(注意:它没有完整解析样式表)。 |
@@ -9,2 +9,3 @@ 'use strict'; | ||
var NodeList = require('./node-list'); | ||
var NamedNodeMap = require('./named-node-map'); | ||
@@ -17,2 +18,5 @@ function Element(ownerDocument, name, namespaceURI) { | ||
value: namespaceURI | ||
}, | ||
_attributes: { | ||
value: new NamedNodeMap() | ||
} | ||
@@ -23,2 +27,7 @@ }); | ||
Element.prototype = Object.create(Node.prototype, { | ||
attributes: { | ||
get: function() { | ||
return this._attributes; | ||
} | ||
}, | ||
id: { | ||
@@ -52,2 +61,3 @@ get: function() { | ||
} | ||
}); | ||
@@ -58,7 +68,7 @@ | ||
Element.prototype.hasAttribute = function(name) { | ||
return this.attributes.getNamedItem(name) !== null; | ||
return this._attributes.getNamedItem(name) !== null; | ||
}; | ||
Element.prototype.getAttribute = function(name) { | ||
var attr = this.attributes.getNamedItem(name); | ||
var attr = this._attributes.getNamedItem(name); | ||
return attr && attr.nodeValue; | ||
@@ -69,11 +79,11 @@ }; | ||
var attr = new Attr(this.ownerDocument, name, true, value); | ||
this.attributes.setNamedItem(attr); | ||
this._attributes.setNamedItem(attr); | ||
}; | ||
Element.prototype.removeAttribute = function(name) { | ||
this.attributes.removeNamedItem(name); | ||
this._attributes.removeNamedItem(name); | ||
}; | ||
Element.prototype.getAttributeNode = function(name) { | ||
return this.attributes.getNamedItem(name); | ||
return this._attributes.getNamedItem(name); | ||
}; | ||
@@ -89,2 +99,6 @@ | ||
Element.prototype.getElementsByClassName = function() { | ||
throw new Error('not yet implemented'); | ||
}; | ||
Element.prototype.querySelector = function(selector) { | ||
@@ -91,0 +105,0 @@ return matcher(this).first(selector, this); |
@@ -11,5 +11,5 @@ 'use strict'; | ||
options: { | ||
// TODO HTMLOptionsCollection | ||
// TODO return HTMLOptionsCollection | ||
get: function() { | ||
return this.querySelectorAll('option'); | ||
return this.getElementsByTagName('option'); | ||
} | ||
@@ -16,0 +16,0 @@ }, |
@@ -9,3 +9,3 @@ 'use strict'; | ||
'FORM': require('./html-form-element'), | ||
// support nwmatcher | ||
'BUTTON': require('./html-button-element'), | ||
@@ -12,0 +12,0 @@ 'INPUT': require('./html-input-element'), |
@@ -11,7 +11,3 @@ 'use strict'; | ||
HTMLElement.prototype = Object.create(Element.prototype, { | ||
lang: { | ||
get: function() { | ||
return this.getAttribute('lang') || ''; | ||
} | ||
}, | ||
style: { | ||
@@ -32,2 +28,9 @@ get: function() { | ||
} | ||
}, | ||
// support nwmatcher | ||
lang: { | ||
get: function() { | ||
return this.getAttribute('lang') || ''; | ||
} | ||
} | ||
@@ -34,0 +37,0 @@ }); |
@@ -5,3 +5,3 @@ 'use strict'; | ||
Object.defineProperties(this, { | ||
_index: { | ||
_indexs: { | ||
value: {} | ||
@@ -19,3 +19,3 @@ } | ||
getNamedItem: function(name) { | ||
return this[this._index[name]] || null; | ||
return this[this._indexs[name]] || null; | ||
}, | ||
@@ -25,3 +25,3 @@ | ||
var name = node.nodeName; | ||
var index = this._index[name]; | ||
var index = this._indexs[name]; | ||
@@ -37,3 +37,3 @@ this[name] = node; | ||
this[this.length] = node; | ||
this._index[name] = this.length; | ||
this._indexs[name] = this.length; | ||
this.length++; | ||
@@ -46,3 +46,3 @@ | ||
removeNamedItem: function(name) { | ||
var index = this._index[name]; | ||
var index = this._indexs[name]; | ||
@@ -58,3 +58,3 @@ delete this[name];; | ||
while (++index < length) { | ||
this._index[this[index].nodeName] = index; | ||
this._indexs[this[index].nodeName] = index; | ||
} | ||
@@ -61,0 +61,0 @@ |
@@ -6,6 +6,7 @@ 'use strict'; | ||
var NodeList = require('./node-list'); | ||
var NamedNodeMap = require('./named-node-map'); | ||
function Node(ownerDocument, nodeName, nodeValue, nodeType) { | ||
// TODO hasAttributes | ||
// TODO hasAttributes() | ||
// TODO contains() | ||
// TODO replaceChild() | ||
Object.defineProperties(this, { | ||
@@ -27,6 +28,4 @@ _parent: { | ||
}, | ||
_attributes: { | ||
value: new NamedNodeMap() | ||
}, | ||
childNodes: { | ||
enumerable: true, | ||
value: new NodeList([]) | ||
@@ -49,12 +48,2 @@ }, | ||
value: ownerDocument | ||
}, | ||
baseURI: { | ||
get: function() { | ||
var base = ownerDocument.getElementsByTagName('base').item(0); | ||
if (base) { | ||
return url.resolve(ownerDocument.URL, base.getAttribute('href')); | ||
} else { | ||
return ownerDocument.URL; | ||
} | ||
} | ||
} | ||
@@ -66,7 +55,7 @@ | ||
Node.ELEMENT_NODE = 1; | ||
Node.ATTRIBUTE_NODE = 2; | ||
Node.ATTRIBUTE_NODE = 2; // 废弃 | ||
Node.TEXT_NODE = 3; | ||
Node.CDATA_SECTION_NODE = 4; | ||
Node.ENTITY_REFERENCE_NODE = 5; | ||
Node.ENTITY_NODE = 6; | ||
Node.CDATA_SECTION_NODE = 4; // 废弃 | ||
Node.ENTITY_REFERENCE_NODE = 5; // 废弃 | ||
Node.ENTITY_NODE = 6; // 废弃 | ||
Node.PROCESSING_INSTRUCTION_NODE = 7; | ||
@@ -77,6 +66,7 @@ Node.COMMENT_NODE = 8; | ||
Node.DOCUMENT_FRAGMENT_NODE = 11; | ||
Node.NOTATION_NODE = 12; | ||
Node.NOTATION_NODE = 12; // 废弃 | ||
Node.prototype = Object.create(Object.prototype, { | ||
parentNode: { | ||
enumerable: true, | ||
get: function() { | ||
@@ -87,2 +77,3 @@ return this._parent; | ||
firstChild: { | ||
enumerable: true, | ||
get: function() { | ||
@@ -93,2 +84,3 @@ return this._first; | ||
lastChild: { | ||
enumerable: true, | ||
get: function() { | ||
@@ -99,2 +91,3 @@ return this._last; | ||
nextSibling: { | ||
enumerable: true, | ||
get: function() { | ||
@@ -105,2 +98,3 @@ return this._next; | ||
previousSibling: { | ||
enumerable: true, | ||
get: function() { | ||
@@ -110,8 +104,16 @@ return this._previous; | ||
}, | ||
attributes: { | ||
baseURI: { | ||
enumerable: true, | ||
get: function() { | ||
return this._attributes; | ||
var ownerDocument = this.ownerDocument; | ||
var base = ownerDocument.getElementsByTagName('base').item(0); | ||
if (base) { | ||
return url.resolve(ownerDocument.URL, base.getAttribute('href')); | ||
} else { | ||
return ownerDocument.URL; | ||
} | ||
} | ||
}, | ||
textContent: { | ||
enumerable: true, | ||
get: function() { | ||
@@ -148,3 +150,10 @@ switch (this.nodeType) { | ||
// TODO test | ||
// Node.prototype.contains = function(element) { | ||
// while ((element = element.parentNode) && element.nodeType == 1) { | ||
// if (element === this) return true; | ||
// } | ||
// return false; | ||
// }; | ||
Node.prototype.insertBefore = function(newChild) { // jshint ignore:line | ||
@@ -180,3 +189,3 @@ throw new Error('not yet implemented'); | ||
// TODO �����Ż� | ||
// TODO 性能优化 | ||
Array.prototype.splice.call(this.childNodes, Array.prototype.indexOf.call(oldChild), 1); | ||
@@ -219,3 +228,3 @@ | ||
// TODO �����Ż� | ||
// TODO 性能优化 | ||
Array.prototype.push.call(this.childNodes, newChild); | ||
@@ -222,0 +231,0 @@ |
67599
40
1829
195