Comparing version 2.0.1 to 2.0.2
23
index.js
'use strict' | ||
module.exports = require('./lib/index') | ||
var parse = require('./lib/parse') | ||
var Parser = require('./lib/Parser') | ||
var escape = require('./lib/escape') | ||
var Element = require('./lib/Element') | ||
/** | ||
* Element | ||
*/ | ||
exports.Element = Element | ||
exports.createElement = Element.createElement | ||
/** | ||
* Helpers | ||
*/ | ||
exports.escapeXML = escape.escapeXML | ||
exports.escapeXMLText = escape.escapeXMLText | ||
/** | ||
* parser interface | ||
*/ | ||
exports.Parser = Parser | ||
exports.parse = parse |
'use strict' | ||
var inherits = require('inherits') | ||
, Element = require('./Element') | ||
var Element = require('./Element') | ||
function DOMElement(name, attrs) { | ||
Element.call(this, name, attrs) | ||
function DOMElement (name, attrs) { | ||
Element.call(this, name, attrs) | ||
this.nodeType = 1 | ||
this.nodeName = this.localName | ||
this.nodeType = 1 | ||
this.nodeName = this.localName | ||
} | ||
@@ -15,108 +15,108 @@ | ||
DOMElement.prototype._getElement = function(name, attrs) { | ||
var element = new DOMElement(name, attrs) | ||
return element | ||
DOMElement.prototype._getElement = function (name, attrs) { | ||
var element = new DOMElement(name, attrs) | ||
return element | ||
} | ||
Object.defineProperty(DOMElement.prototype, 'localName', { | ||
get: function () { | ||
return this.getName() | ||
} | ||
get: function () { | ||
return this.getName() | ||
} | ||
}) | ||
Object.defineProperty(DOMElement.prototype, 'namespaceURI', { | ||
get: function () { | ||
return this.getNS() | ||
} | ||
get: function () { | ||
return this.getNS() | ||
} | ||
}) | ||
Object.defineProperty(DOMElement.prototype, 'parentNode', { | ||
get: function () { | ||
return this.parent | ||
} | ||
get: function () { | ||
return this.parent | ||
} | ||
}) | ||
Object.defineProperty(DOMElement.prototype, 'childNodes', { | ||
get: function () { | ||
return this.children | ||
} | ||
get: function () { | ||
return this.children | ||
} | ||
}) | ||
Object.defineProperty(DOMElement.prototype, 'textContent', { | ||
get: function () { | ||
return this.getText() | ||
}, | ||
set: function (value) { | ||
this.children.push(value) | ||
} | ||
get: function () { | ||
return this.getText() | ||
}, | ||
set: function (value) { | ||
this.children.push(value) | ||
} | ||
}) | ||
DOMElement.prototype.getElementsByTagName = function (name) { | ||
return this.getChildren(name) | ||
return this.getChildren(name) | ||
} | ||
DOMElement.prototype.getAttribute = function (name) { | ||
return this.getAttr(name) | ||
return this.getAttr(name) | ||
} | ||
DOMElement.prototype.setAttribute = function (name, value) { | ||
this.attr(name, value) | ||
this.attr(name, value) | ||
} | ||
DOMElement.prototype.getAttributeNS = function (ns, name) { | ||
if (ns === 'http://www.w3.org/XML/1998/namespace') { | ||
return this.getAttr(['xml', name].join(':')) | ||
} | ||
return this.getAttr(name, ns) | ||
if (ns === 'http://www.w3.org/XML/1998/namespace') { | ||
return this.getAttr(['xml', name].join(':')) | ||
} | ||
return this.getAttr(name, ns) | ||
} | ||
DOMElement.prototype.setAttributeNS = function (ns, name, value) { | ||
var prefix | ||
if (ns === 'http://www.w3.org/XML/1998/namespace') { | ||
prefix = 'xml' | ||
} else { | ||
var nss = this.getXmlns() | ||
prefix = nss[ns] || '' | ||
} | ||
if (prefix) { | ||
this.attr([prefix, name].join(':'), value) | ||
} | ||
var prefix | ||
if (ns === 'http://www.w3.org/XML/1998/namespace') { | ||
prefix = 'xml' | ||
} else { | ||
var nss = this.getXmlns() | ||
prefix = nss[ns] || '' | ||
} | ||
if (prefix) { | ||
this.attr([prefix, name].join(':'), value) | ||
} | ||
} | ||
DOMElement.prototype.removeAttribute = function (name) { | ||
this.attr(name, null) | ||
this.attr(name, null) | ||
} | ||
DOMElement.prototype.removeAttributeNS = function (ns, name) { | ||
var prefix | ||
if (ns === 'http://www.w3.org/XML/1998/namespace') { | ||
prefix = 'xml' | ||
} else { | ||
var nss = this.getXmlns() | ||
prefix = nss[ns] || '' | ||
} | ||
if (prefix) { | ||
this.attr([prefix, name].join(':'), null) | ||
} | ||
var prefix | ||
if (ns === 'http://www.w3.org/XML/1998/namespace') { | ||
prefix = 'xml' | ||
} else { | ||
var nss = this.getXmlns() | ||
prefix = nss[ns] || '' | ||
} | ||
if (prefix) { | ||
this.attr([prefix, name].join(':'), null) | ||
} | ||
} | ||
DOMElement.prototype.appendChild = function (el) { | ||
this.cnode(el) | ||
this.cnode(el) | ||
} | ||
DOMElement.prototype.removeChild = function (el) { | ||
this.remove(el) | ||
this.remove(el) | ||
} | ||
DOMElement.createElement = function(name, attrs /*, child1, child2, ...*/) { | ||
var el = new DOMElement(name, attrs) | ||
DOMElement.createElement = function (name, attrs /*, child1, child2, ...*/) { | ||
var el = new DOMElement(name, attrs) | ||
var children = Array.prototype.slice.call(arguments, 2) | ||
var children = Array.prototype.slice.call(arguments, 2) | ||
children.forEach(function(child) { | ||
el.appendChild(child) | ||
}) | ||
return el | ||
children.forEach(function (child) { | ||
el.appendChild(child) | ||
}) | ||
return el | ||
} | ||
module.exports = DOMElement |
@@ -13,10 +13,10 @@ 'use strict' | ||
**/ | ||
function Element(name, attrs) { | ||
this.name = name | ||
this.parent = null | ||
this.children = [] | ||
this.setAttrs(attrs) | ||
function Element (name, attrs) { | ||
this.name = name | ||
this.parent = null | ||
this.children = [] | ||
this.setAttrs(attrs) | ||
} | ||
/*** Accessors ***/ | ||
/* Accessors */ | ||
@@ -26,14 +26,14 @@ /** | ||
**/ | ||
Element.prototype.is = function(name, xmlns) { | ||
return (this.getName() === name) && | ||
(!xmlns || (this.getNS() === xmlns)) | ||
Element.prototype.is = function (name, xmlns) { | ||
return (this.getName() === name) && | ||
(!xmlns || (this.getNS() === xmlns)) | ||
} | ||
/* without prefix */ | ||
Element.prototype.getName = function() { | ||
if (this.name.indexOf(':') >= 0) { | ||
return this.name.substr(this.name.indexOf(':') + 1) | ||
} else { | ||
return this.name | ||
} | ||
Element.prototype.getName = function () { | ||
if (this.name.indexOf(':') >= 0) { | ||
return this.name.substr(this.name.indexOf(':') + 1) | ||
} else { | ||
return this.name | ||
} | ||
} | ||
@@ -44,8 +44,8 @@ | ||
**/ | ||
Element.prototype.getNS = function() { | ||
if (this.name.indexOf(':') >= 0) { | ||
var prefix = this.name.substr(0, this.name.indexOf(':')) | ||
return this.findNS(prefix) | ||
} | ||
return this.findNS() | ||
Element.prototype.getNS = function () { | ||
if (this.name.indexOf(':') >= 0) { | ||
var prefix = this.name.substr(0, this.name.indexOf(':')) | ||
return this.findNS(prefix) | ||
} | ||
return this.findNS() | ||
} | ||
@@ -56,19 +56,19 @@ | ||
**/ | ||
Element.prototype.findNS = function(prefix) { | ||
if (!prefix) { | ||
/* default namespace */ | ||
if (this.attrs.xmlns) { | ||
return this.attrs.xmlns | ||
} else if (this.parent) { | ||
return this.parent.findNS() | ||
} | ||
} else { | ||
/* prefixed namespace */ | ||
var attr = 'xmlns:' + prefix | ||
if (this.attrs[attr]) { | ||
return this.attrs[attr] | ||
} else if (this.parent) { | ||
return this.parent.findNS(prefix) | ||
} | ||
Element.prototype.findNS = function (prefix) { | ||
if (!prefix) { | ||
/* default namespace */ | ||
if (this.attrs.xmlns) { | ||
return this.attrs.xmlns | ||
} else if (this.parent) { | ||
return this.parent.findNS() | ||
} | ||
} else { | ||
/* prefixed namespace */ | ||
var attr = 'xmlns:' + prefix | ||
if (this.attrs[attr]) { | ||
return this.attrs[attr] | ||
} else if (this.parent) { | ||
return this.parent.findNS(prefix) | ||
} | ||
} | ||
} | ||
@@ -79,28 +79,28 @@ | ||
**/ | ||
Element.prototype.getXmlns = function() { | ||
var namespaces = {} | ||
Element.prototype.getXmlns = function () { | ||
var namespaces = {} | ||
if (this.parent) { | ||
namespaces = this.parent.getXmlns() | ||
} | ||
if (this.parent) { | ||
namespaces = this.parent.getXmlns() | ||
} | ||
for (var attr in this.attrs) { | ||
var m = attr.match('xmlns:?(.*)') | ||
if (this.attrs.hasOwnProperty(attr) && m) { | ||
namespaces[this.attrs[attr]] = m[1] | ||
} | ||
for (var attr in this.attrs) { | ||
var m = attr.match('xmlns:?(.*)') | ||
if (this.attrs.hasOwnProperty(attr) && m) { | ||
namespaces[this.attrs[attr]] = m[1] | ||
} | ||
return namespaces | ||
} | ||
return namespaces | ||
} | ||
Element.prototype.setAttrs = function(attrs) { | ||
this.attrs = {} | ||
Element.prototype.setAttrs = function (attrs) { | ||
this.attrs = {} | ||
if (typeof attrs === 'string') | ||
this.attrs.xmlns = attrs | ||
else if (attrs) { | ||
Object.keys(attrs).forEach(function(key) { | ||
this.attrs[key] = attrs[key] | ||
}, this) | ||
} | ||
if (typeof attrs === 'string') { | ||
this.attrs.xmlns = attrs | ||
} else if (attrs) { | ||
Object.keys(attrs).forEach(function (key) { | ||
this.attrs[key] = attrs[key] | ||
}, this) | ||
} | ||
} | ||
@@ -111,14 +111,14 @@ | ||
**/ | ||
Element.prototype.getAttr = function(name, xmlns) { | ||
if (!xmlns) { | ||
return this.attrs[name] | ||
} | ||
Element.prototype.getAttr = function (name, xmlns) { | ||
if (!xmlns) { | ||
return this.attrs[name] | ||
} | ||
var namespaces = this.getXmlns() | ||
var namespaces = this.getXmlns() | ||
if (!namespaces[xmlns]) { | ||
return null | ||
} | ||
if (!namespaces[xmlns]) { | ||
return null | ||
} | ||
return this.attrs[[namespaces[xmlns], name].join(':')] | ||
return this.attrs[[namespaces[xmlns], name].join(':')] | ||
} | ||
@@ -129,4 +129,4 @@ | ||
**/ | ||
Element.prototype.getChild = function(name, xmlns) { | ||
return this.getChildren(name, xmlns)[0] | ||
Element.prototype.getChild = function (name, xmlns) { | ||
return this.getChildren(name, xmlns)[0] | ||
} | ||
@@ -137,12 +137,13 @@ | ||
**/ | ||
Element.prototype.getChildren = function(name, xmlns) { | ||
var result = [] | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if (child.getName && | ||
(child.getName() === name) && | ||
(!xmlns || (child.getNS() === xmlns))) | ||
result.push(child) | ||
Element.prototype.getChildren = function (name, xmlns) { | ||
var result = [] | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if (child.getName && | ||
(child.getName() === name) && | ||
(!xmlns || (child.getNS() === xmlns))) { | ||
result.push(child) | ||
} | ||
return result | ||
} | ||
return result | ||
} | ||
@@ -153,4 +154,4 @@ | ||
**/ | ||
Element.prototype.getChildByAttr = function(attr, val, xmlns, recursive) { | ||
return this.getChildrenByAttr(attr, val, xmlns, recursive)[0] | ||
Element.prototype.getChildByAttr = function (attr, val, xmlns, recursive) { | ||
return this.getChildrenByAttr(attr, val, xmlns, recursive)[0] | ||
} | ||
@@ -161,50 +162,52 @@ | ||
**/ | ||
Element.prototype.getChildrenByAttr = function(attr, val, xmlns, recursive) { | ||
var result = [] | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if (child.attrs && | ||
(child.attrs[attr] === val) && | ||
(!xmlns || (child.getNS() === xmlns))) | ||
result.push(child) | ||
if (recursive && child.getChildrenByAttr) { | ||
result.push(child.getChildrenByAttr(attr, val, xmlns, true)) | ||
} | ||
Element.prototype.getChildrenByAttr = function (attr, val, xmlns, recursive) { | ||
var result = [] | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if (child.attrs && | ||
(child.attrs[attr] === val) && | ||
(!xmlns || (child.getNS() === xmlns))) { | ||
result.push(child) | ||
} | ||
if (recursive) { | ||
result = [].concat.apply([], result) | ||
if (recursive && child.getChildrenByAttr) { | ||
result.push(child.getChildrenByAttr(attr, val, xmlns, true)) | ||
} | ||
return result | ||
} | ||
if (recursive) { | ||
result = [].concat.apply([], result) | ||
} | ||
return result | ||
} | ||
Element.prototype.getChildrenByFilter = function(filter, recursive) { | ||
var result = [] | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if (filter(child)) | ||
result.push(child) | ||
if (recursive && child.getChildrenByFilter){ | ||
result.push(child.getChildrenByFilter(filter, true)) | ||
} | ||
Element.prototype.getChildrenByFilter = function (filter, recursive) { | ||
var result = [] | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if (filter(child)) { | ||
result.push(child) | ||
} | ||
if (recursive) { | ||
result = [].concat.apply([], result) | ||
if (recursive && child.getChildrenByFilter) { | ||
result.push(child.getChildrenByFilter(filter, true)) | ||
} | ||
return result | ||
} | ||
if (recursive) { | ||
result = [].concat.apply([], result) | ||
} | ||
return result | ||
} | ||
Element.prototype.getText = function() { | ||
var text = '' | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if ((typeof child === 'string') || (typeof child === 'number')) { | ||
text += child | ||
} | ||
Element.prototype.getText = function () { | ||
var text = '' | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if ((typeof child === 'string') || (typeof child === 'number')) { | ||
text += child | ||
} | ||
return text | ||
} | ||
return text | ||
} | ||
Element.prototype.getChildText = function(name, xmlns) { | ||
var child = this.getChild(name, xmlns) | ||
return child ? child.getText() : null | ||
Element.prototype.getChildText = function (name, xmlns) { | ||
var child = this.getChild(name, xmlns) | ||
return child ? child.getText() : null | ||
} | ||
@@ -217,16 +220,16 @@ | ||
*/ | ||
Element.prototype.getChildElements = function() { | ||
return this.getChildrenByFilter(function(child) { | ||
return child instanceof Element | ||
}) | ||
Element.prototype.getChildElements = function () { | ||
return this.getChildrenByFilter(function (child) { | ||
return child instanceof Element | ||
}) | ||
} | ||
/*** Builder ***/ | ||
/* Builder */ | ||
/** returns uppermost parent */ | ||
Element.prototype.root = function() { | ||
if (this.parent) { | ||
return this.parent.root() | ||
} | ||
return this | ||
Element.prototype.root = function () { | ||
if (this.parent) { | ||
return this.parent.root() | ||
} | ||
return this | ||
} | ||
@@ -236,34 +239,34 @@ Element.prototype.tree = Element.prototype.root | ||
/** just parent or itself */ | ||
Element.prototype.up = function() { | ||
if (this.parent) { | ||
return this.parent | ||
} | ||
return this | ||
Element.prototype.up = function () { | ||
if (this.parent) { | ||
return this.parent | ||
} | ||
return this | ||
} | ||
Element.prototype._getElement = function(name, attrs) { | ||
var element = new Element(name, attrs) | ||
return element | ||
Element.prototype._getElement = function (name, attrs) { | ||
var element = new Element(name, attrs) | ||
return element | ||
} | ||
/** create child node and return it */ | ||
Element.prototype.c = function(name, attrs) { | ||
return this.cnode(this._getElement(name, attrs)) | ||
Element.prototype.c = function (name, attrs) { | ||
return this.cnode(this._getElement(name, attrs)) | ||
} | ||
Element.prototype.cnode = function(child) { | ||
this.children.push(child) | ||
if (typeof child === 'object') { | ||
child.parent = this | ||
} | ||
return child | ||
Element.prototype.cnode = function (child) { | ||
this.children.push(child) | ||
if (typeof child === 'object') { | ||
child.parent = this | ||
} | ||
return child | ||
} | ||
/** add text node and return element */ | ||
Element.prototype.t = function(text) { | ||
this.children.push(text) | ||
return this | ||
Element.prototype.t = function (text) { | ||
this.children.push(text) | ||
return this | ||
} | ||
/*** Manipulation ***/ | ||
/* Manipulation */ | ||
@@ -275,20 +278,20 @@ /** | ||
*/ | ||
Element.prototype.remove = function(el, xmlns) { | ||
var filter | ||
if (typeof el === 'string') { | ||
/* 1st parameter is tag name */ | ||
filter = function(child) { | ||
return !(child.is && | ||
child.is(el, xmlns)) | ||
} | ||
} else { | ||
/* 1st parameter is element */ | ||
filter = function(child) { | ||
return child !== el | ||
} | ||
Element.prototype.remove = function (el, xmlns) { | ||
var filter | ||
if (typeof el === 'string') { | ||
/* 1st parameter is tag name */ | ||
filter = function (child) { | ||
return !(child.is && | ||
child.is(el, xmlns)) | ||
} | ||
} else { | ||
/* 1st parameter is element */ | ||
filter = function (child) { | ||
return child !== el | ||
} | ||
} | ||
this.children = this.children.filter(filter) | ||
this.children = this.children.filter(filter) | ||
return this | ||
return this | ||
} | ||
@@ -301,104 +304,104 @@ | ||
*/ | ||
Element.prototype.clone = function() { | ||
var clone = this._getElement(this.name, this.attrs) | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
clone.cnode(child.clone ? child.clone() : child) | ||
} | ||
return clone | ||
Element.prototype.clone = function () { | ||
var clone = this._getElement(this.name, this.attrs) | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
clone.cnode(child.clone ? child.clone() : child) | ||
} | ||
return clone | ||
} | ||
Element.prototype.text = function(val) { | ||
if (val && this.children.length === 1) { | ||
this.children[0] = val | ||
return this | ||
} | ||
return this.getText() | ||
Element.prototype.text = function (val) { | ||
if (val && this.children.length === 1) { | ||
this.children[0] = val | ||
return this | ||
} | ||
return this.getText() | ||
} | ||
Element.prototype.attr = function(attr, val) { | ||
if (((typeof val !== 'undefined') || (val === null))) { | ||
if (!this.attrs) { | ||
this.attrs = {} | ||
} | ||
this.attrs[attr] = val | ||
return this | ||
Element.prototype.attr = function (attr, val) { | ||
if (typeof val !== 'undefined' || val === null) { | ||
if (!this.attrs) { | ||
this.attrs = {} | ||
} | ||
return this.attrs[attr] | ||
this.attrs[attr] = val | ||
return this | ||
} | ||
return this.attrs[attr] | ||
} | ||
/*** Serialization ***/ | ||
/* Serialization */ | ||
Element.prototype.toString = function() { | ||
var s = '' | ||
this.write(function(c) { | ||
s += c | ||
}) | ||
return s | ||
Element.prototype.toString = function () { | ||
var s = '' | ||
this.write(function (c) { | ||
s += c | ||
}) | ||
return s | ||
} | ||
Element.prototype.toJSON = function() { | ||
return { | ||
name: this.name, | ||
attrs: this.attrs, | ||
children: this.children.map(function(child) { | ||
return child && child.toJSON ? child.toJSON() : child | ||
}) | ||
} | ||
Element.prototype.toJSON = function () { | ||
return { | ||
name: this.name, | ||
attrs: this.attrs, | ||
children: this.children.map(function (child) { | ||
return child && child.toJSON ? child.toJSON() : child | ||
}) | ||
} | ||
} | ||
Element.prototype._addChildren = function(writer) { | ||
writer('>') | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
/* Skip null/undefined */ | ||
if (child || (child === 0)) { | ||
if (child.write) { | ||
child.write(writer) | ||
} else if (typeof child === 'string') { | ||
writer(escapeXMLText(child)) | ||
} else if (child.toString) { | ||
writer(escapeXMLText(child.toString(10))) | ||
} | ||
} | ||
Element.prototype._addChildren = function (writer) { | ||
writer('>') | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
/* Skip null/undefined */ | ||
if (child || (child === 0)) { | ||
if (child.write) { | ||
child.write(writer) | ||
} else if (typeof child === 'string') { | ||
writer(escapeXMLText(child)) | ||
} else if (child.toString) { | ||
writer(escapeXMLText(child.toString(10))) | ||
} | ||
} | ||
writer('</') | ||
writer(this.name) | ||
writer('>') | ||
} | ||
writer('</') | ||
writer(this.name) | ||
writer('>') | ||
} | ||
Element.prototype.write = function(writer) { | ||
writer('<') | ||
writer(this.name) | ||
for (var k in this.attrs) { | ||
var v = this.attrs[k] | ||
if (v || (v === '') || (v === 0)) { | ||
writer(' ') | ||
writer(k) | ||
writer('="') | ||
if (typeof v !== 'string') { | ||
v = v.toString(10) | ||
} | ||
writer(escapeXML(v)) | ||
writer('"') | ||
} | ||
Element.prototype.write = function (writer) { | ||
writer('<') | ||
writer(this.name) | ||
for (var k in this.attrs) { | ||
var v = this.attrs[k] | ||
if (v || (v === '') || (v === 0)) { | ||
writer(' ') | ||
writer(k) | ||
writer('="') | ||
if (typeof v !== 'string') { | ||
v = v.toString(10) | ||
} | ||
writer(escapeXML(v)) | ||
writer('"') | ||
} | ||
if (this.children.length === 0) { | ||
writer('/>') | ||
} else { | ||
this._addChildren(writer) | ||
} | ||
} | ||
if (this.children.length === 0) { | ||
writer('/>') | ||
} else { | ||
this._addChildren(writer) | ||
} | ||
} | ||
Element.createElement = function(name, attrs /*, child1, child2, ...*/) { | ||
var el = new Element(name, attrs) | ||
Element.createElement = function (name, attrs /*, child1, child2, ...*/) { | ||
var el = new Element(name, attrs) | ||
var children = Array.prototype.slice.call(arguments, 2) | ||
var children = Array.prototype.slice.call(arguments, 2) | ||
children.forEach(function(child) { | ||
el.cnode(child) | ||
}) | ||
return el | ||
children.forEach(function (child) { | ||
el.cnode(child) | ||
}) | ||
return el | ||
} | ||
module.exports = Element |
'use strict' | ||
module.exports.escapeXML = function escapeXML(s) { | ||
return s. | ||
replace(/\&/g, '&'). | ||
replace(/</g, '<'). | ||
replace(/>/g, '>'). | ||
replace(/"/g, '"'). | ||
replace(/"/g, ''') | ||
exports.escapeXML = function escapeXML (s) { | ||
return s | ||
.replace(/\&/g, '&') | ||
.replace(/</g, '<') | ||
.replace(/>/g, '>') | ||
.replace(/"/g, '"') | ||
.replace(/"/g, ''') | ||
} | ||
module.exports.escapeXMLText = function escapeXMLText(s) { | ||
return s. | ||
replace(/\&/g, '&'). | ||
replace(/</g, '<'). | ||
replace(/>/g, '>') | ||
exports.escapeXMLText = function escapeXMLText (s) { | ||
return s | ||
.replace(/\&/g, '&') | ||
.replace(/</g, '<') | ||
.replace(/>/g, '>') | ||
} |
@@ -5,22 +5,22 @@ 'use strict' | ||
module.exports = function parse(data, options) { | ||
var p = new Parser(options) | ||
var result = null | ||
, error = null | ||
module.exports = function parse (data, options) { | ||
var p = new Parser(options) | ||
var result = null | ||
var error = null | ||
p.on('tree', function(tree) { | ||
result = tree | ||
}) | ||
p.on('error', function(e) { | ||
error = e | ||
}) | ||
p.on('tree', function (tree) { | ||
result = tree | ||
}) | ||
p.on('error', function (e) { | ||
error = e | ||
}) | ||
p.write(data) | ||
p.end() | ||
p.write(data) | ||
p.end() | ||
if (error) { | ||
throw error | ||
} else { | ||
return result | ||
} | ||
if (error) { | ||
throw error | ||
} else { | ||
return result | ||
} | ||
} |
@@ -8,43 +8,41 @@ 'use strict' | ||
var Parser = function(options) { | ||
EventEmitter.call(this) | ||
var Parser = function (options) { | ||
EventEmitter.call(this) | ||
var ParserInterface = this.Parser = (options && options.Parser) || LtxParser | ||
var ElementInterface = this.Element = (options && options.Element) || Element | ||
var ParserInterface = this.Parser = (options && options.Parser) || LtxParser | ||
var ElementInterface = this.Element = (options && options.Element) || Element | ||
this.parser = new ParserInterface() | ||
this.parser = new ParserInterface() | ||
var el | ||
, self = this | ||
this.parser.on('startElement', function(name, attrs) { | ||
var child = new ElementInterface(name, attrs) | ||
if (!el) { | ||
el = child | ||
} else { | ||
el = el.cnode(child) | ||
} | ||
}) | ||
this.parser.on('endElement', function(name) { | ||
/* jshint -W035 */ | ||
if (!el) { | ||
/* Err */ | ||
} else if (name === el.name) { | ||
if (el.parent) { | ||
el = el.parent | ||
} else if (!self.tree) { | ||
self.tree = el | ||
el = undefined | ||
} | ||
} | ||
/* jshint +W035 */ | ||
}) | ||
this.parser.on('text', function(str) { | ||
if (el) { | ||
el.t(str) | ||
} | ||
}) | ||
this.parser.on('error', function(e) { | ||
self.error = e | ||
self.emit('error', e) | ||
}) | ||
var el | ||
var self = this | ||
this.parser.on('startElement', function (name, attrs) { | ||
var child = new ElementInterface(name, attrs) | ||
if (!el) { | ||
el = child | ||
} else { | ||
el = el.cnode(child) | ||
} | ||
}) | ||
this.parser.on('endElement', function (name) { | ||
if (!el) { | ||
/* Err */ | ||
} else if (name === el.name) { | ||
if (el.parent) { | ||
el = el.parent | ||
} else if (!self.tree) { | ||
self.tree = el | ||
el = undefined | ||
} | ||
} | ||
}) | ||
this.parser.on('text', function (str) { | ||
if (el) { | ||
el.t(str) | ||
} | ||
}) | ||
this.parser.on('error', function (e) { | ||
self.error = e | ||
self.emit('error', e) | ||
}) | ||
} | ||
@@ -54,18 +52,18 @@ | ||
Parser.prototype.write = function(data) { | ||
this.parser.write(data) | ||
Parser.prototype.write = function (data) { | ||
this.parser.write(data) | ||
} | ||
Parser.prototype.end = function(data) { | ||
this.parser.end(data) | ||
Parser.prototype.end = function (data) { | ||
this.parser.end(data) | ||
if (!this.error) { | ||
if (this.tree) { | ||
this.emit('tree', this.tree) | ||
} else { | ||
this.emit('error', new Error('Incomplete document')) | ||
} | ||
if (!this.error) { | ||
if (this.tree) { | ||
this.emit('tree', this.tree) | ||
} else { | ||
this.emit('error', new Error('Incomplete document')) | ||
} | ||
} | ||
} | ||
module.exports = Parser |
'use strict' | ||
var inherits = require('inherits') | ||
, EventEmitter = require('events').EventEmitter | ||
, Easysax = require('easysax') | ||
var EventEmitter = require('events').EventEmitter | ||
var Easysax = require('easysax') | ||
@@ -13,49 +13,47 @@ /** | ||
function SaxEasysax () { | ||
EventEmitter.call(this) | ||
this.parser = new Easysax() | ||
function SaxEasysax() { | ||
EventEmitter.call(this) | ||
this.parser = new Easysax() | ||
var self = this | ||
var self = this | ||
this.parser.on('startNode', function (name, attr, uq) { | ||
attr = attr() | ||
this.parser.on('startNode', function(name, attr, uq) { | ||
attr = attr() | ||
if (attr === false) { | ||
self.emit('error', 'attr char') | ||
return false | ||
} | ||
if (attr === false) { | ||
self.emit('error', 'attr char') | ||
return false | ||
} | ||
for (var k in attr) { | ||
attr[k] = uq(attr[k]) | ||
} | ||
for(var k in attr) { | ||
attr[k] = uq(attr[k]) | ||
} | ||
self.emit('startElement', name, attr) | ||
}) | ||
this.parser.on('endNode', function (name) { | ||
self.emit('endElement', name) | ||
}) | ||
this.parser.on('textNode', function (str, uq) { | ||
self.emit('text', uq(str)) | ||
}) | ||
this.parser.on('cdata', function (str) { | ||
self.emit('text', str) | ||
}) | ||
this.parser.on('error', function (e) { | ||
self.emit('error', e) | ||
}) | ||
// TODO: other events, esp. entityDecl (billion laughs!) | ||
self.emit('startElement', name, attr) | ||
}) | ||
/* jshint -W098 */ | ||
this.parser.on('endNode', function(name) { | ||
self.emit('endElement', name) | ||
}) | ||
this.parser.on('textNode', function(str, uq) { | ||
self.emit('text', uq(str)) | ||
}) | ||
this.parser.on('cdata', function(str) { | ||
self.emit('text', str) | ||
}) | ||
this.parser.on('error', function(e) { | ||
self.emit('error', e) | ||
}) | ||
// TODO: other events, esp. entityDecl (billion laughs!) | ||
var sbuffer = '' | ||
var sbuffer = '' | ||
this.write = function (data) { | ||
sbuffer += typeof data !== 'string' ? data.toString() : data | ||
} | ||
this.write = function(data) { | ||
sbuffer += typeof data !== 'string' ? data.toString() : data | ||
} | ||
this.end = function(data) { | ||
sbuffer += typeof data !== 'string' ? data.toString() : data | ||
this.parser(sbuffer) | ||
sbuffer = '' | ||
} | ||
this.end = function (data) { | ||
sbuffer += typeof data !== 'string' ? data.toString() : data | ||
this.parser(sbuffer) | ||
sbuffer = '' | ||
} | ||
} |
'use strict' | ||
module.exports = [ | ||
// 'easysax', | ||
'ltx', | ||
'node-expat', | ||
'node-xml', | ||
'sax' | ||
].map(function(name) { | ||
return require('./' + name) | ||
// 'easysax', | ||
'ltx', | ||
'node-expat', | ||
'node-xml', | ||
'sax' | ||
].map(function (name) { | ||
return require('./' + name) | ||
}) |
'use strict' | ||
var inherits = require('inherits') | ||
, EventEmitter = require('events').EventEmitter | ||
var EventEmitter = require('events').EventEmitter | ||
var STATE_TEXT = 0, | ||
STATE_IGNORE_TAG = 1, | ||
STATE_TAG_NAME = 2, | ||
STATE_TAG = 3, | ||
STATE_ATTR_NAME = 4, | ||
STATE_ATTR_EQ = 5, | ||
STATE_ATTR_QUOT = 6, | ||
STATE_ATTR_VALUE = 7 | ||
var STATE_TEXT = 0 | ||
var STATE_IGNORE_TAG = 1 | ||
var STATE_TAG_NAME = 2 | ||
var STATE_TAG = 3 | ||
var STATE_ATTR_NAME = 4 | ||
var STATE_ATTR_EQ = 5 | ||
var STATE_ATTR_QUOT = 6 | ||
var STATE_ATTR_VALUE = 7 | ||
var SaxLtx = module.exports = function SaxLtx() { | ||
EventEmitter.call(this) | ||
var SaxLtx = module.exports = function SaxLtx () { | ||
EventEmitter.call(this) | ||
var state = STATE_TEXT, remainder | ||
var tagName, attrs, endTag, selfClosing, attrQuote | ||
var recordStart = 0 | ||
var attrName | ||
var state = STATE_TEXT | ||
var remainder | ||
var tagName | ||
var attrs | ||
var endTag | ||
var selfClosing | ||
var attrQuote | ||
var recordStart = 0 | ||
var attrName | ||
this._handleTagOpening = function(endTag, tagName, attrs) { | ||
if (!endTag) { | ||
this.emit('startElement', tagName, attrs) | ||
if (selfClosing) { | ||
this.emit('endElement', tagName) | ||
} | ||
} else { | ||
this.emit('endElement', tagName) | ||
} | ||
this._handleTagOpening = function (endTag, tagName, attrs) { | ||
if (!endTag) { | ||
this.emit('startElement', tagName, attrs) | ||
if (selfClosing) { | ||
this.emit('endElement', tagName) | ||
} | ||
} else { | ||
this.emit('endElement', tagName) | ||
} | ||
} | ||
this.write = function(data) { | ||
/* jshint -W071 */ | ||
/* jshint -W074 */ | ||
if (typeof data !== 'string') { | ||
data = data.toString() | ||
} | ||
var pos = 0 | ||
this.write = function (data) { | ||
if (typeof data !== 'string') { | ||
data = data.toString() | ||
} | ||
var pos = 0 | ||
/* Anything from previous write()? */ | ||
if (remainder) { | ||
data = remainder + data | ||
pos += remainder.length | ||
remainder = null | ||
} | ||
/* Anything from previous write()? */ | ||
if (remainder) { | ||
data = remainder + data | ||
pos += remainder.length | ||
remainder = null | ||
} | ||
function endRecording() { | ||
if (typeof recordStart === 'number') { | ||
var recorded = data.slice(recordStart, pos) | ||
recordStart = undefined | ||
return recorded | ||
} | ||
} | ||
function endRecording () { | ||
if (typeof recordStart === 'number') { | ||
var recorded = data.slice(recordStart, pos) | ||
recordStart = undefined | ||
return recorded | ||
} | ||
} | ||
for(; pos < data.length; pos++) { | ||
var c = data.charCodeAt(pos) | ||
//console.log("state", state, "c", c, data[pos]) | ||
switch(state) { | ||
case STATE_TEXT: | ||
if (c === 60 /* < */) { | ||
var text = endRecording() | ||
if (text) { | ||
this.emit('text', unescapeXml(text)) | ||
} | ||
state = STATE_TAG_NAME | ||
recordStart = pos + 1 | ||
attrs = {} | ||
} | ||
break | ||
case STATE_TAG_NAME: | ||
if (c === 47 /* / */ && recordStart === pos) { | ||
recordStart = pos + 1 | ||
endTag = true | ||
} else if (c === 33 /* ! */ || c === 63 /* ? */) { | ||
recordStart = undefined | ||
state = STATE_IGNORE_TAG | ||
} else if (c <= 32 || c === 47 /* / */ || c === 62 /* > */) { | ||
tagName = endRecording() | ||
pos-- | ||
state = STATE_TAG | ||
} | ||
break | ||
case STATE_IGNORE_TAG: | ||
if (c === 62 /* > */) { | ||
state = STATE_TEXT | ||
} | ||
break | ||
case STATE_TAG: | ||
if (c === 62 /* > */) { | ||
this._handleTagOpening(endTag, tagName, attrs) | ||
tagName = undefined | ||
attrs = undefined | ||
endTag = undefined | ||
selfClosing = undefined | ||
state = STATE_TEXT | ||
recordStart = pos + 1 | ||
} else if (c === 47 /* / */) { | ||
selfClosing = true | ||
} else if (c > 32) { | ||
recordStart = pos | ||
state = STATE_ATTR_NAME | ||
} | ||
break | ||
case STATE_ATTR_NAME: | ||
if (c <= 32 || c === 61 /* = */) { | ||
attrName = endRecording() | ||
pos-- | ||
state = STATE_ATTR_EQ | ||
} | ||
break | ||
case STATE_ATTR_EQ: | ||
if (c === 61 /* = */) { | ||
state = STATE_ATTR_QUOT | ||
} | ||
break | ||
case STATE_ATTR_QUOT: | ||
if (c === 34 /* " */ || c === 39 /* ' */) { | ||
attrQuote = c | ||
state = STATE_ATTR_VALUE | ||
recordStart = pos + 1 | ||
} | ||
break | ||
case STATE_ATTR_VALUE: | ||
if (c === attrQuote) { | ||
var value = unescapeXml(endRecording()) | ||
attrs[attrName] = value | ||
attrName = undefined | ||
state = STATE_TAG | ||
} | ||
break | ||
for (; pos < data.length; pos++) { | ||
var c = data.charCodeAt(pos) | ||
// console.log("state", state, "c", c, data[pos]) | ||
switch (state) { | ||
case STATE_TEXT: | ||
if (c === 60 /* < */) { | ||
var text = endRecording() | ||
if (text) { | ||
this.emit('text', unescapeXml(text)) | ||
} | ||
} | ||
state = STATE_TAG_NAME | ||
recordStart = pos + 1 | ||
attrs = {} | ||
} | ||
break | ||
case STATE_TAG_NAME: | ||
if (c === 47 /* / */ && recordStart === pos) { | ||
recordStart = pos + 1 | ||
endTag = true | ||
} else if (c === 33 /* ! */ || c === 63 /* ? */) { | ||
recordStart = undefined | ||
state = STATE_IGNORE_TAG | ||
} else if (c <= 32 || c === 47 /* / */ || c === 62 /* > */) { | ||
tagName = endRecording() | ||
pos-- | ||
state = STATE_TAG | ||
} | ||
break | ||
case STATE_IGNORE_TAG: | ||
if (c === 62 /* > */) { | ||
state = STATE_TEXT | ||
} | ||
break | ||
case STATE_TAG: | ||
if (c === 62 /* > */) { | ||
this._handleTagOpening(endTag, tagName, attrs) | ||
tagName = undefined | ||
attrs = undefined | ||
endTag = undefined | ||
selfClosing = undefined | ||
state = STATE_TEXT | ||
recordStart = pos + 1 | ||
} else if (c === 47 /* / */) { | ||
selfClosing = true | ||
} else if (c > 32) { | ||
recordStart = pos | ||
state = STATE_ATTR_NAME | ||
} | ||
break | ||
case STATE_ATTR_NAME: | ||
if (c <= 32 || c === 61 /* = */) { | ||
attrName = endRecording() | ||
pos-- | ||
state = STATE_ATTR_EQ | ||
} | ||
break | ||
case STATE_ATTR_EQ: | ||
if (c === 61 /* = */) { | ||
state = STATE_ATTR_QUOT | ||
} | ||
break | ||
case STATE_ATTR_QUOT: | ||
if (c === 34 /* " */ || c === 39 /* ' */) { | ||
attrQuote = c | ||
state = STATE_ATTR_VALUE | ||
recordStart = pos + 1 | ||
} | ||
break | ||
case STATE_ATTR_VALUE: | ||
if (c === attrQuote) { | ||
var value = unescapeXml(endRecording()) | ||
attrs[attrName] = value | ||
attrName = undefined | ||
state = STATE_TAG | ||
} | ||
break | ||
} | ||
} | ||
if (typeof recordStart === 'number' && | ||
recordStart <= data.length) { | ||
remainder = data.slice(recordStart) | ||
recordStart = 0 | ||
} | ||
if (typeof recordStart === 'number' && | ||
recordStart <= data.length) { | ||
remainder = data.slice(recordStart) | ||
recordStart = 0 | ||
} | ||
/*var origEmit = this.emit | ||
this.emit = function() { | ||
} | ||
/* | ||
var origEmit = this.emit | ||
this.emit = function() { | ||
console.log('ltx', arguments) | ||
origEmit.apply(this, arguments) | ||
}*/ | ||
} | ||
*/ | ||
} | ||
inherits(SaxLtx, EventEmitter) | ||
SaxLtx.prototype.end = function (data) { | ||
if (data) { | ||
this.write(data) | ||
} | ||
SaxLtx.prototype.end = function(data) { | ||
if (data) { | ||
this.write(data) | ||
} | ||
/* Uh, yeah */ | ||
this.write = function() {} | ||
/* Uh, yeah */ | ||
this.write = function () {} | ||
} | ||
function unescapeXml(s) { | ||
return s. | ||
replace(/\&(amp|#38);/g, '&'). | ||
replace(/\&(lt|#60);/g, '<'). | ||
replace(/\&(gt|#62);/g, '>'). | ||
replace(/\&(quot|#34);/g, '"'). | ||
replace(/\&(apos|#39);/g, '\''). | ||
replace(/\&(nbsp|#160);/g, '\n') | ||
function unescapeXml (s) { | ||
return s | ||
.replace(/\&(amp|#38);/g, '&') | ||
.replace(/\&(lt|#60);/g, '<') | ||
.replace(/\&(gt|#62);/g, '>') | ||
.replace(/\&(quot|#34);/g, '"') | ||
.replace(/\&(apos|#39);/g, "'") | ||
.replace(/\&(nbsp|#160);/g, '\n') | ||
} |
'use strict' | ||
var inherits = require('inherits') | ||
, EventEmitter = require('events').EventEmitter | ||
, expat = require('node-expat') | ||
var EventEmitter = require('events').EventEmitter | ||
var expat = require('node-expat') | ||
var SaxExpat = module.exports = function SaxExpat() { | ||
EventEmitter.call(this) | ||
this.parser = new expat.Parser('UTF-8') | ||
var SaxExpat = module.exports = function SaxExpat () { | ||
EventEmitter.call(this) | ||
this.parser = new expat.Parser('UTF-8') | ||
var that = this | ||
this.parser.on('startElement', function(name, attrs) { | ||
that.emit('startElement', name, attrs) | ||
}) | ||
this.parser.on('endElement', function(name) { | ||
that.emit('endElement', name) | ||
}) | ||
this.parser.on('text', function(str) { | ||
that.emit('text', str) | ||
}) | ||
// TODO: other events, esp. entityDecl (billion laughs!) | ||
var that = this | ||
this.parser.on('startElement', function (name, attrs) { | ||
that.emit('startElement', name, attrs) | ||
}) | ||
this.parser.on('endElement', function (name) { | ||
that.emit('endElement', name) | ||
}) | ||
this.parser.on('text', function (str) { | ||
that.emit('text', str) | ||
}) | ||
// TODO: other events, esp. entityDecl (billion laughs!) | ||
} | ||
@@ -26,19 +26,19 @@ | ||
SaxExpat.prototype.write = function(data) { | ||
if (!this.parser.parse(data, false)) { | ||
this.emit('error', new Error(this.parser.getError())) | ||
SaxExpat.prototype.write = function (data) { | ||
if (!this.parser.parse(data, false)) { | ||
this.emit('error', new Error(this.parser.getError())) | ||
// Premature error thrown, | ||
// disable all functionality: | ||
this.write = function() { } | ||
this.end = function() { } | ||
} | ||
// Premature error thrown, | ||
// disable all functionality: | ||
this.write = function () {} | ||
this.end = function () {} | ||
} | ||
} | ||
SaxExpat.prototype.end = function() { | ||
if (!this.parser.parse('', true)) { | ||
this.emit('error', new Error(this.parser.getError())) | ||
} else { | ||
this.emit('end') | ||
} | ||
SaxExpat.prototype.end = function () { | ||
if (!this.parser.parse('', true)) { | ||
this.emit('error', new Error(this.parser.getError())) | ||
} else { | ||
this.emit('end') | ||
} | ||
} |
'use strict' | ||
var inherits = require('inherits') | ||
, EventEmitter = require('events').EventEmitter | ||
, xml = require('node-xml') | ||
var EventEmitter = require('events').EventEmitter | ||
var xml = require('node-xml') | ||
@@ -11,40 +11,40 @@ /** | ||
*/ | ||
var SaxNodeXML = module.exports = function SaxNodeXML() { | ||
EventEmitter.call(this) | ||
var self = this | ||
this.parser = new xml.SaxParser(function(handler) { | ||
/* jshint -W072 */ | ||
handler.onStartElementNS(function(elem, attrs, prefix, uri, namespaces) { | ||
var i, attrsHash = {} | ||
if (prefix) { | ||
elem = prefix + ':' + elem | ||
} | ||
for (i = 0; i < attrs.length; i++) { | ||
var attr = attrs[i] | ||
attrsHash[attr[0]] = unescapeXml(attr[1]) | ||
} | ||
for(i = 0; i < namespaces.length; i++) { | ||
var namespace = namespaces[i] | ||
var k = !namespace[0] ? 'xmlns' : 'xmlns:' + namespace[0] | ||
attrsHash[k] = unescapeXml(namespace[1]) | ||
} | ||
self.emit('startElement', elem, attrsHash) | ||
}) | ||
handler.onEndElementNS(function(elem, prefix) { | ||
if (prefix) { | ||
elem = prefix + ':' + elem | ||
} | ||
self.emit('endElement', elem) | ||
}) | ||
handler.onCharacters(function(str) { | ||
self.emit('text', str) | ||
}) | ||
handler.onCdata(function(str) { | ||
self.emit('text', str) | ||
}) | ||
handler.onError(function(e) { | ||
self.emit('error', e) | ||
}) | ||
// TODO: other events, esp. entityDecl (billion laughs!) | ||
var SaxNodeXML = module.exports = function SaxNodeXML () { | ||
EventEmitter.call(this) | ||
var self = this | ||
this.parser = new xml.SaxParser(function (handler) { | ||
handler.onStartElementNS(function (elem, attrs, prefix, uri, namespaces) { | ||
var i | ||
var attrsHash = {} | ||
if (prefix) { | ||
elem = prefix + ':' + elem | ||
} | ||
for (i = 0; i < attrs.length; i++) { | ||
var attr = attrs[i] | ||
attrsHash[attr[0]] = unescapeXml(attr[1]) | ||
} | ||
for (i = 0; i < namespaces.length; i++) { | ||
var namespace = namespaces[i] | ||
var k = !namespace[0] ? 'xmlns' : 'xmlns:' + namespace[0] | ||
attrsHash[k] = unescapeXml(namespace[1]) | ||
} | ||
self.emit('startElement', elem, attrsHash) | ||
}) | ||
handler.onEndElementNS(function (elem, prefix) { | ||
if (prefix) { | ||
elem = prefix + ':' + elem | ||
} | ||
self.emit('endElement', elem) | ||
}) | ||
handler.onCharacters(function (str) { | ||
self.emit('text', str) | ||
}) | ||
handler.onCdata(function (str) { | ||
self.emit('text', str) | ||
}) | ||
handler.onError(function (e) { | ||
self.emit('error', e) | ||
}) | ||
// TODO: other events, esp. entityDecl (billion laughs!) | ||
}) | ||
} | ||
@@ -54,19 +54,19 @@ | ||
SaxNodeXML.prototype.write = function(data) { | ||
this.parser.parseString(data) | ||
SaxNodeXML.prototype.write = function (data) { | ||
this.parser.parseString(data) | ||
} | ||
SaxNodeXML.prototype.end = function(data) { | ||
if (data) { | ||
this.write(data) | ||
} | ||
SaxNodeXML.prototype.end = function (data) { | ||
if (data) { | ||
this.write(data) | ||
} | ||
} | ||
function unescapeXml(s) { | ||
return s. | ||
replace(/\&/g, '&'). | ||
replace(/\</g, '<'). | ||
replace(/\>/g, '>'). | ||
replace(/\"/g, '"'). | ||
replace(/\'/g, '\'') | ||
function unescapeXml (s) { | ||
return s | ||
.replace(/\&/g, '&') | ||
.replace(/\</g, '<') | ||
.replace(/\>/g, '>') | ||
.replace(/\"/g, '"') | ||
.replace(/\'/g, "'") | ||
} |
'use strict' | ||
var inherits = require('inherits') | ||
, EventEmitter = require('events').EventEmitter | ||
, sax = require('sax') | ||
var EventEmitter = require('events').EventEmitter | ||
var sax = require('sax') | ||
var SaxSaxjs = module.exports = function SaxSaxjs() { | ||
var SaxSaxjs = module.exports = function SaxSaxjs () { | ||
EventEmitter.call(this) | ||
this.parser = sax.parser(true) | ||
EventEmitter.call(this) | ||
this.parser = sax.parser(true) | ||
var that = this | ||
this.parser.onopentag = function(a) { | ||
that.emit('startElement', a.name, a.attributes) | ||
} | ||
this.parser.onclosetag = function(name) { | ||
that.emit('endElement', name) | ||
} | ||
this.parser.ontext = function(str) { | ||
that.emit('text', str) | ||
} | ||
this.parser.onend = function() { | ||
that.emit('end') | ||
} | ||
this.parser.onerror = function(e) { | ||
that.emit('error', e) | ||
} | ||
// TODO: other events, esp. entityDecl (billion laughs!) | ||
var that = this | ||
this.parser.onopentag = function (a) { | ||
that.emit('startElement', a.name, a.attributes) | ||
} | ||
this.parser.onclosetag = function (name) { | ||
that.emit('endElement', name) | ||
} | ||
this.parser.ontext = function (str) { | ||
that.emit('text', str) | ||
} | ||
this.parser.onend = function () { | ||
that.emit('end') | ||
} | ||
this.parser.onerror = function (e) { | ||
that.emit('error', e) | ||
} | ||
// TODO: other events, esp. entityDecl (billion laughs!) | ||
} | ||
@@ -33,14 +32,14 @@ | ||
SaxSaxjs.prototype.write = function(data) { | ||
if (typeof data !== 'string') { | ||
data = data.toString() | ||
} | ||
this.parser.write(data) | ||
SaxSaxjs.prototype.write = function (data) { | ||
if (typeof data !== 'string') { | ||
data = data.toString() | ||
} | ||
this.parser.write(data) | ||
} | ||
SaxSaxjs.prototype.end = function(data) { | ||
if (data) { | ||
this.parser.write(data) | ||
} | ||
this.parser.close() | ||
SaxSaxjs.prototype.end = function (data) { | ||
if (data) { | ||
this.parser.write(data) | ||
} | ||
this.parser.close() | ||
} |
993
ltx.js
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ltx = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
'use strict' | ||
var parse = require('./lib/parse') | ||
var Parser = require('./lib/Parser') | ||
var escape = require('./lib/escape') | ||
var Element = require('./lib/Element') | ||
/** | ||
* Element | ||
*/ | ||
exports.Element = Element | ||
exports.createElement = Element.createElement | ||
/** | ||
* Helpers | ||
*/ | ||
exports.escapeXML = escape.escapeXML | ||
exports.escapeXMLText = escape.escapeXMLText | ||
/** | ||
* parser interface | ||
*/ | ||
exports.Parser = Parser | ||
exports.parse = parse | ||
},{"./lib/Element":2,"./lib/Parser":3,"./lib/escape":4,"./lib/parse":5}],2:[function(require,module,exports){ | ||
'use strict' | ||
var escape = require('./escape') | ||
@@ -14,10 +40,10 @@ var escapeXML = escape.escapeXML | ||
**/ | ||
function Element(name, attrs) { | ||
this.name = name | ||
this.parent = null | ||
this.children = [] | ||
this.setAttrs(attrs) | ||
function Element (name, attrs) { | ||
this.name = name | ||
this.parent = null | ||
this.children = [] | ||
this.setAttrs(attrs) | ||
} | ||
/*** Accessors ***/ | ||
/* Accessors */ | ||
@@ -27,14 +53,14 @@ /** | ||
**/ | ||
Element.prototype.is = function(name, xmlns) { | ||
return (this.getName() === name) && | ||
(!xmlns || (this.getNS() === xmlns)) | ||
Element.prototype.is = function (name, xmlns) { | ||
return (this.getName() === name) && | ||
(!xmlns || (this.getNS() === xmlns)) | ||
} | ||
/* without prefix */ | ||
Element.prototype.getName = function() { | ||
if (this.name.indexOf(':') >= 0) { | ||
return this.name.substr(this.name.indexOf(':') + 1) | ||
} else { | ||
return this.name | ||
} | ||
Element.prototype.getName = function () { | ||
if (this.name.indexOf(':') >= 0) { | ||
return this.name.substr(this.name.indexOf(':') + 1) | ||
} else { | ||
return this.name | ||
} | ||
} | ||
@@ -45,8 +71,8 @@ | ||
**/ | ||
Element.prototype.getNS = function() { | ||
if (this.name.indexOf(':') >= 0) { | ||
var prefix = this.name.substr(0, this.name.indexOf(':')) | ||
return this.findNS(prefix) | ||
} | ||
return this.findNS() | ||
Element.prototype.getNS = function () { | ||
if (this.name.indexOf(':') >= 0) { | ||
var prefix = this.name.substr(0, this.name.indexOf(':')) | ||
return this.findNS(prefix) | ||
} | ||
return this.findNS() | ||
} | ||
@@ -57,19 +83,19 @@ | ||
**/ | ||
Element.prototype.findNS = function(prefix) { | ||
if (!prefix) { | ||
/* default namespace */ | ||
if (this.attrs.xmlns) { | ||
return this.attrs.xmlns | ||
} else if (this.parent) { | ||
return this.parent.findNS() | ||
} | ||
} else { | ||
/* prefixed namespace */ | ||
var attr = 'xmlns:' + prefix | ||
if (this.attrs[attr]) { | ||
return this.attrs[attr] | ||
} else if (this.parent) { | ||
return this.parent.findNS(prefix) | ||
} | ||
Element.prototype.findNS = function (prefix) { | ||
if (!prefix) { | ||
/* default namespace */ | ||
if (this.attrs.xmlns) { | ||
return this.attrs.xmlns | ||
} else if (this.parent) { | ||
return this.parent.findNS() | ||
} | ||
} else { | ||
/* prefixed namespace */ | ||
var attr = 'xmlns:' + prefix | ||
if (this.attrs[attr]) { | ||
return this.attrs[attr] | ||
} else if (this.parent) { | ||
return this.parent.findNS(prefix) | ||
} | ||
} | ||
} | ||
@@ -80,28 +106,28 @@ | ||
**/ | ||
Element.prototype.getXmlns = function() { | ||
var namespaces = {} | ||
Element.prototype.getXmlns = function () { | ||
var namespaces = {} | ||
if (this.parent) { | ||
namespaces = this.parent.getXmlns() | ||
} | ||
if (this.parent) { | ||
namespaces = this.parent.getXmlns() | ||
} | ||
for (var attr in this.attrs) { | ||
var m = attr.match('xmlns:?(.*)') | ||
if (this.attrs.hasOwnProperty(attr) && m) { | ||
namespaces[this.attrs[attr]] = m[1] | ||
} | ||
for (var attr in this.attrs) { | ||
var m = attr.match('xmlns:?(.*)') | ||
if (this.attrs.hasOwnProperty(attr) && m) { | ||
namespaces[this.attrs[attr]] = m[1] | ||
} | ||
return namespaces | ||
} | ||
return namespaces | ||
} | ||
Element.prototype.setAttrs = function(attrs) { | ||
this.attrs = {} | ||
Element.prototype.setAttrs = function (attrs) { | ||
this.attrs = {} | ||
if (typeof attrs === 'string') | ||
this.attrs.xmlns = attrs | ||
else if (attrs) { | ||
Object.keys(attrs).forEach(function(key) { | ||
this.attrs[key] = attrs[key] | ||
}, this) | ||
} | ||
if (typeof attrs === 'string') { | ||
this.attrs.xmlns = attrs | ||
} else if (attrs) { | ||
Object.keys(attrs).forEach(function (key) { | ||
this.attrs[key] = attrs[key] | ||
}, this) | ||
} | ||
} | ||
@@ -112,14 +138,14 @@ | ||
**/ | ||
Element.prototype.getAttr = function(name, xmlns) { | ||
if (!xmlns) { | ||
return this.attrs[name] | ||
} | ||
Element.prototype.getAttr = function (name, xmlns) { | ||
if (!xmlns) { | ||
return this.attrs[name] | ||
} | ||
var namespaces = this.getXmlns() | ||
var namespaces = this.getXmlns() | ||
if (!namespaces[xmlns]) { | ||
return null | ||
} | ||
if (!namespaces[xmlns]) { | ||
return null | ||
} | ||
return this.attrs[[namespaces[xmlns], name].join(':')] | ||
return this.attrs[[namespaces[xmlns], name].join(':')] | ||
} | ||
@@ -130,4 +156,4 @@ | ||
**/ | ||
Element.prototype.getChild = function(name, xmlns) { | ||
return this.getChildren(name, xmlns)[0] | ||
Element.prototype.getChild = function (name, xmlns) { | ||
return this.getChildren(name, xmlns)[0] | ||
} | ||
@@ -138,12 +164,13 @@ | ||
**/ | ||
Element.prototype.getChildren = function(name, xmlns) { | ||
var result = [] | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if (child.getName && | ||
(child.getName() === name) && | ||
(!xmlns || (child.getNS() === xmlns))) | ||
result.push(child) | ||
Element.prototype.getChildren = function (name, xmlns) { | ||
var result = [] | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if (child.getName && | ||
(child.getName() === name) && | ||
(!xmlns || (child.getNS() === xmlns))) { | ||
result.push(child) | ||
} | ||
return result | ||
} | ||
return result | ||
} | ||
@@ -154,4 +181,4 @@ | ||
**/ | ||
Element.prototype.getChildByAttr = function(attr, val, xmlns, recursive) { | ||
return this.getChildrenByAttr(attr, val, xmlns, recursive)[0] | ||
Element.prototype.getChildByAttr = function (attr, val, xmlns, recursive) { | ||
return this.getChildrenByAttr(attr, val, xmlns, recursive)[0] | ||
} | ||
@@ -162,50 +189,52 @@ | ||
**/ | ||
Element.prototype.getChildrenByAttr = function(attr, val, xmlns, recursive) { | ||
var result = [] | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if (child.attrs && | ||
(child.attrs[attr] === val) && | ||
(!xmlns || (child.getNS() === xmlns))) | ||
result.push(child) | ||
if (recursive && child.getChildrenByAttr) { | ||
result.push(child.getChildrenByAttr(attr, val, xmlns, true)) | ||
} | ||
Element.prototype.getChildrenByAttr = function (attr, val, xmlns, recursive) { | ||
var result = [] | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if (child.attrs && | ||
(child.attrs[attr] === val) && | ||
(!xmlns || (child.getNS() === xmlns))) { | ||
result.push(child) | ||
} | ||
if (recursive) { | ||
result = [].concat.apply([], result) | ||
if (recursive && child.getChildrenByAttr) { | ||
result.push(child.getChildrenByAttr(attr, val, xmlns, true)) | ||
} | ||
return result | ||
} | ||
if (recursive) { | ||
result = [].concat.apply([], result) | ||
} | ||
return result | ||
} | ||
Element.prototype.getChildrenByFilter = function(filter, recursive) { | ||
var result = [] | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if (filter(child)) | ||
result.push(child) | ||
if (recursive && child.getChildrenByFilter){ | ||
result.push(child.getChildrenByFilter(filter, true)) | ||
} | ||
Element.prototype.getChildrenByFilter = function (filter, recursive) { | ||
var result = [] | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if (filter(child)) { | ||
result.push(child) | ||
} | ||
if (recursive) { | ||
result = [].concat.apply([], result) | ||
if (recursive && child.getChildrenByFilter) { | ||
result.push(child.getChildrenByFilter(filter, true)) | ||
} | ||
return result | ||
} | ||
if (recursive) { | ||
result = [].concat.apply([], result) | ||
} | ||
return result | ||
} | ||
Element.prototype.getText = function() { | ||
var text = '' | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if ((typeof child === 'string') || (typeof child === 'number')) { | ||
text += child | ||
} | ||
Element.prototype.getText = function () { | ||
var text = '' | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
if ((typeof child === 'string') || (typeof child === 'number')) { | ||
text += child | ||
} | ||
return text | ||
} | ||
return text | ||
} | ||
Element.prototype.getChildText = function(name, xmlns) { | ||
var child = this.getChild(name, xmlns) | ||
return child ? child.getText() : null | ||
Element.prototype.getChildText = function (name, xmlns) { | ||
var child = this.getChild(name, xmlns) | ||
return child ? child.getText() : null | ||
} | ||
@@ -218,16 +247,16 @@ | ||
*/ | ||
Element.prototype.getChildElements = function() { | ||
return this.getChildrenByFilter(function(child) { | ||
return child instanceof Element | ||
}) | ||
Element.prototype.getChildElements = function () { | ||
return this.getChildrenByFilter(function (child) { | ||
return child instanceof Element | ||
}) | ||
} | ||
/*** Builder ***/ | ||
/* Builder */ | ||
/** returns uppermost parent */ | ||
Element.prototype.root = function() { | ||
if (this.parent) { | ||
return this.parent.root() | ||
} | ||
return this | ||
Element.prototype.root = function () { | ||
if (this.parent) { | ||
return this.parent.root() | ||
} | ||
return this | ||
} | ||
@@ -237,34 +266,34 @@ Element.prototype.tree = Element.prototype.root | ||
/** just parent or itself */ | ||
Element.prototype.up = function() { | ||
if (this.parent) { | ||
return this.parent | ||
} | ||
return this | ||
Element.prototype.up = function () { | ||
if (this.parent) { | ||
return this.parent | ||
} | ||
return this | ||
} | ||
Element.prototype._getElement = function(name, attrs) { | ||
var element = new Element(name, attrs) | ||
return element | ||
Element.prototype._getElement = function (name, attrs) { | ||
var element = new Element(name, attrs) | ||
return element | ||
} | ||
/** create child node and return it */ | ||
Element.prototype.c = function(name, attrs) { | ||
return this.cnode(this._getElement(name, attrs)) | ||
Element.prototype.c = function (name, attrs) { | ||
return this.cnode(this._getElement(name, attrs)) | ||
} | ||
Element.prototype.cnode = function(child) { | ||
this.children.push(child) | ||
if (typeof child === 'object') { | ||
child.parent = this | ||
} | ||
return child | ||
Element.prototype.cnode = function (child) { | ||
this.children.push(child) | ||
if (typeof child === 'object') { | ||
child.parent = this | ||
} | ||
return child | ||
} | ||
/** add text node and return element */ | ||
Element.prototype.t = function(text) { | ||
this.children.push(text) | ||
return this | ||
Element.prototype.t = function (text) { | ||
this.children.push(text) | ||
return this | ||
} | ||
/*** Manipulation ***/ | ||
/* Manipulation */ | ||
@@ -276,20 +305,20 @@ /** | ||
*/ | ||
Element.prototype.remove = function(el, xmlns) { | ||
var filter | ||
if (typeof el === 'string') { | ||
/* 1st parameter is tag name */ | ||
filter = function(child) { | ||
return !(child.is && | ||
child.is(el, xmlns)) | ||
} | ||
} else { | ||
/* 1st parameter is element */ | ||
filter = function(child) { | ||
return child !== el | ||
} | ||
Element.prototype.remove = function (el, xmlns) { | ||
var filter | ||
if (typeof el === 'string') { | ||
/* 1st parameter is tag name */ | ||
filter = function (child) { | ||
return !(child.is && | ||
child.is(el, xmlns)) | ||
} | ||
} else { | ||
/* 1st parameter is element */ | ||
filter = function (child) { | ||
return child !== el | ||
} | ||
} | ||
this.children = this.children.filter(filter) | ||
this.children = this.children.filter(filter) | ||
return this | ||
return this | ||
} | ||
@@ -302,102 +331,102 @@ | ||
*/ | ||
Element.prototype.clone = function() { | ||
var clone = this._getElement(this.name, this.attrs) | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
clone.cnode(child.clone ? child.clone() : child) | ||
} | ||
return clone | ||
Element.prototype.clone = function () { | ||
var clone = this._getElement(this.name, this.attrs) | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
clone.cnode(child.clone ? child.clone() : child) | ||
} | ||
return clone | ||
} | ||
Element.prototype.text = function(val) { | ||
if (val && this.children.length === 1) { | ||
this.children[0] = val | ||
return this | ||
} | ||
return this.getText() | ||
Element.prototype.text = function (val) { | ||
if (val && this.children.length === 1) { | ||
this.children[0] = val | ||
return this | ||
} | ||
return this.getText() | ||
} | ||
Element.prototype.attr = function(attr, val) { | ||
if (((typeof val !== 'undefined') || (val === null))) { | ||
if (!this.attrs) { | ||
this.attrs = {} | ||
} | ||
this.attrs[attr] = val | ||
return this | ||
Element.prototype.attr = function (attr, val) { | ||
if (typeof val !== 'undefined' || val === null) { | ||
if (!this.attrs) { | ||
this.attrs = {} | ||
} | ||
return this.attrs[attr] | ||
this.attrs[attr] = val | ||
return this | ||
} | ||
return this.attrs[attr] | ||
} | ||
/*** Serialization ***/ | ||
/* Serialization */ | ||
Element.prototype.toString = function() { | ||
var s = '' | ||
this.write(function(c) { | ||
s += c | ||
}) | ||
return s | ||
Element.prototype.toString = function () { | ||
var s = '' | ||
this.write(function (c) { | ||
s += c | ||
}) | ||
return s | ||
} | ||
Element.prototype.toJSON = function() { | ||
return { | ||
name: this.name, | ||
attrs: this.attrs, | ||
children: this.children.map(function(child) { | ||
return child && child.toJSON ? child.toJSON() : child | ||
}) | ||
} | ||
Element.prototype.toJSON = function () { | ||
return { | ||
name: this.name, | ||
attrs: this.attrs, | ||
children: this.children.map(function (child) { | ||
return child && child.toJSON ? child.toJSON() : child | ||
}) | ||
} | ||
} | ||
Element.prototype._addChildren = function(writer) { | ||
writer('>') | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
/* Skip null/undefined */ | ||
if (child || (child === 0)) { | ||
if (child.write) { | ||
child.write(writer) | ||
} else if (typeof child === 'string') { | ||
writer(escapeXMLText(child)) | ||
} else if (child.toString) { | ||
writer(escapeXMLText(child.toString(10))) | ||
} | ||
} | ||
Element.prototype._addChildren = function (writer) { | ||
writer('>') | ||
for (var i = 0; i < this.children.length; i++) { | ||
var child = this.children[i] | ||
/* Skip null/undefined */ | ||
if (child || (child === 0)) { | ||
if (child.write) { | ||
child.write(writer) | ||
} else if (typeof child === 'string') { | ||
writer(escapeXMLText(child)) | ||
} else if (child.toString) { | ||
writer(escapeXMLText(child.toString(10))) | ||
} | ||
} | ||
writer('</') | ||
writer(this.name) | ||
writer('>') | ||
} | ||
writer('</') | ||
writer(this.name) | ||
writer('>') | ||
} | ||
Element.prototype.write = function(writer) { | ||
writer('<') | ||
writer(this.name) | ||
for (var k in this.attrs) { | ||
var v = this.attrs[k] | ||
if (v || (v === '') || (v === 0)) { | ||
writer(' ') | ||
writer(k) | ||
writer('="') | ||
if (typeof v !== 'string') { | ||
v = v.toString(10) | ||
} | ||
writer(escapeXML(v)) | ||
writer('"') | ||
} | ||
Element.prototype.write = function (writer) { | ||
writer('<') | ||
writer(this.name) | ||
for (var k in this.attrs) { | ||
var v = this.attrs[k] | ||
if (v || (v === '') || (v === 0)) { | ||
writer(' ') | ||
writer(k) | ||
writer('="') | ||
if (typeof v !== 'string') { | ||
v = v.toString(10) | ||
} | ||
writer(escapeXML(v)) | ||
writer('"') | ||
} | ||
if (this.children.length === 0) { | ||
writer('/>') | ||
} else { | ||
this._addChildren(writer) | ||
} | ||
} | ||
if (this.children.length === 0) { | ||
writer('/>') | ||
} else { | ||
this._addChildren(writer) | ||
} | ||
} | ||
Element.createElement = function(name, attrs /*, child1, child2, ...*/) { | ||
var el = new Element(name, attrs) | ||
Element.createElement = function (name, attrs /*, child1, child2, ...*/) { | ||
var el = new Element(name, attrs) | ||
var children = Array.prototype.slice.call(arguments, 2) | ||
var children = Array.prototype.slice.call(arguments, 2) | ||
children.forEach(function(child) { | ||
el.cnode(child) | ||
}) | ||
return el | ||
children.forEach(function (child) { | ||
el.cnode(child) | ||
}) | ||
return el | ||
} | ||
@@ -407,3 +436,3 @@ | ||
},{"./escape":3}],2:[function(require,module,exports){ | ||
},{"./escape":4}],3:[function(require,module,exports){ | ||
'use strict' | ||
@@ -416,43 +445,41 @@ | ||
var Parser = function(options) { | ||
EventEmitter.call(this) | ||
var Parser = function (options) { | ||
EventEmitter.call(this) | ||
var ParserInterface = this.Parser = (options && options.Parser) || LtxParser | ||
var ElementInterface = this.Element = (options && options.Element) || Element | ||
var ParserInterface = this.Parser = (options && options.Parser) || LtxParser | ||
var ElementInterface = this.Element = (options && options.Element) || Element | ||
this.parser = new ParserInterface() | ||
this.parser = new ParserInterface() | ||
var el | ||
, self = this | ||
this.parser.on('startElement', function(name, attrs) { | ||
var child = new ElementInterface(name, attrs) | ||
if (!el) { | ||
el = child | ||
} else { | ||
el = el.cnode(child) | ||
} | ||
}) | ||
this.parser.on('endElement', function(name) { | ||
/* jshint -W035 */ | ||
if (!el) { | ||
/* Err */ | ||
} else if (name === el.name) { | ||
if (el.parent) { | ||
el = el.parent | ||
} else if (!self.tree) { | ||
self.tree = el | ||
el = undefined | ||
} | ||
} | ||
/* jshint +W035 */ | ||
}) | ||
this.parser.on('text', function(str) { | ||
if (el) { | ||
el.t(str) | ||
} | ||
}) | ||
this.parser.on('error', function(e) { | ||
self.error = e | ||
self.emit('error', e) | ||
}) | ||
var el | ||
var self = this | ||
this.parser.on('startElement', function (name, attrs) { | ||
var child = new ElementInterface(name, attrs) | ||
if (!el) { | ||
el = child | ||
} else { | ||
el = el.cnode(child) | ||
} | ||
}) | ||
this.parser.on('endElement', function (name) { | ||
if (!el) { | ||
/* Err */ | ||
} else if (name === el.name) { | ||
if (el.parent) { | ||
el = el.parent | ||
} else if (!self.tree) { | ||
self.tree = el | ||
el = undefined | ||
} | ||
} | ||
}) | ||
this.parser.on('text', function (str) { | ||
if (el) { | ||
el.t(str) | ||
} | ||
}) | ||
this.parser.on('error', function (e) { | ||
self.error = e | ||
self.emit('error', e) | ||
}) | ||
} | ||
@@ -462,16 +489,16 @@ | ||
Parser.prototype.write = function(data) { | ||
this.parser.write(data) | ||
Parser.prototype.write = function (data) { | ||
this.parser.write(data) | ||
} | ||
Parser.prototype.end = function(data) { | ||
this.parser.end(data) | ||
Parser.prototype.end = function (data) { | ||
this.parser.end(data) | ||
if (!this.error) { | ||
if (this.tree) { | ||
this.emit('tree', this.tree) | ||
} else { | ||
this.emit('error', new Error('Incomplete document')) | ||
} | ||
if (!this.error) { | ||
if (this.tree) { | ||
this.emit('tree', this.tree) | ||
} else { | ||
this.emit('error', new Error('Incomplete document')) | ||
} | ||
} | ||
} | ||
@@ -481,244 +508,220 @@ | ||
},{"./Element":1,"./parsers/ltx":6,"events":8,"inherits":7}],3:[function(require,module,exports){ | ||
},{"./Element":2,"./parsers/ltx":6,"events":8,"inherits":7}],4:[function(require,module,exports){ | ||
'use strict' | ||
module.exports.escapeXML = function escapeXML(s) { | ||
return s. | ||
replace(/\&/g, '&'). | ||
replace(/</g, '<'). | ||
replace(/>/g, '>'). | ||
replace(/"/g, '"'). | ||
replace(/"/g, ''') | ||
exports.escapeXML = function escapeXML (s) { | ||
return s | ||
.replace(/\&/g, '&') | ||
.replace(/</g, '<') | ||
.replace(/>/g, '>') | ||
.replace(/"/g, '"') | ||
.replace(/"/g, ''') | ||
} | ||
module.exports.escapeXMLText = function escapeXMLText(s) { | ||
return s. | ||
replace(/\&/g, '&'). | ||
replace(/</g, '<'). | ||
replace(/>/g, '>') | ||
exports.escapeXMLText = function escapeXMLText (s) { | ||
return s | ||
.replace(/\&/g, '&') | ||
.replace(/</g, '<') | ||
.replace(/>/g, '>') | ||
} | ||
},{}],4:[function(require,module,exports){ | ||
},{}],5:[function(require,module,exports){ | ||
'use strict' | ||
var parse = require('./parse') | ||
var Parser = require('./Parser') | ||
var escape = require('./escape') | ||
var Element = require('./Element') | ||
/** | ||
* Element | ||
*/ | ||
exports.Element = Element | ||
exports.createElement = Element.createElement | ||
module.exports = function parse (data, options) { | ||
var p = new Parser(options) | ||
var result = null | ||
var error = null | ||
/** | ||
* Helpers | ||
*/ | ||
exports.escapeXML = escape.escapeXML | ||
exports.escapeXMLText = escape.escapeXMLText | ||
p.on('tree', function (tree) { | ||
result = tree | ||
}) | ||
p.on('error', function (e) { | ||
error = e | ||
}) | ||
/** | ||
* parser interface | ||
*/ | ||
exports.Parser = Parser | ||
exports.parse = parse | ||
p.write(data) | ||
p.end() | ||
},{"./Element":1,"./Parser":2,"./escape":3,"./parse":5}],5:[function(require,module,exports){ | ||
'use strict' | ||
var Parser = require('./Parser') | ||
module.exports = function parse(data, options) { | ||
var p = new Parser(options) | ||
var result = null | ||
, error = null | ||
p.on('tree', function(tree) { | ||
result = tree | ||
}) | ||
p.on('error', function(e) { | ||
error = e | ||
}) | ||
p.write(data) | ||
p.end() | ||
if (error) { | ||
throw error | ||
} else { | ||
return result | ||
} | ||
if (error) { | ||
throw error | ||
} else { | ||
return result | ||
} | ||
} | ||
},{"./Parser":2}],6:[function(require,module,exports){ | ||
},{"./Parser":3}],6:[function(require,module,exports){ | ||
'use strict' | ||
var inherits = require('inherits') | ||
, EventEmitter = require('events').EventEmitter | ||
var EventEmitter = require('events').EventEmitter | ||
var STATE_TEXT = 0, | ||
STATE_IGNORE_TAG = 1, | ||
STATE_TAG_NAME = 2, | ||
STATE_TAG = 3, | ||
STATE_ATTR_NAME = 4, | ||
STATE_ATTR_EQ = 5, | ||
STATE_ATTR_QUOT = 6, | ||
STATE_ATTR_VALUE = 7 | ||
var STATE_TEXT = 0 | ||
var STATE_IGNORE_TAG = 1 | ||
var STATE_TAG_NAME = 2 | ||
var STATE_TAG = 3 | ||
var STATE_ATTR_NAME = 4 | ||
var STATE_ATTR_EQ = 5 | ||
var STATE_ATTR_QUOT = 6 | ||
var STATE_ATTR_VALUE = 7 | ||
var SaxLtx = module.exports = function SaxLtx() { | ||
EventEmitter.call(this) | ||
var SaxLtx = module.exports = function SaxLtx () { | ||
EventEmitter.call(this) | ||
var state = STATE_TEXT, remainder | ||
var tagName, attrs, endTag, selfClosing, attrQuote | ||
var recordStart = 0 | ||
var attrName | ||
var state = STATE_TEXT | ||
var remainder | ||
var tagName | ||
var attrs | ||
var endTag | ||
var selfClosing | ||
var attrQuote | ||
var recordStart = 0 | ||
var attrName | ||
this._handleTagOpening = function(endTag, tagName, attrs) { | ||
if (!endTag) { | ||
this.emit('startElement', tagName, attrs) | ||
if (selfClosing) { | ||
this.emit('endElement', tagName) | ||
} | ||
} else { | ||
this.emit('endElement', tagName) | ||
} | ||
this._handleTagOpening = function (endTag, tagName, attrs) { | ||
if (!endTag) { | ||
this.emit('startElement', tagName, attrs) | ||
if (selfClosing) { | ||
this.emit('endElement', tagName) | ||
} | ||
} else { | ||
this.emit('endElement', tagName) | ||
} | ||
} | ||
this.write = function(data) { | ||
/* jshint -W071 */ | ||
/* jshint -W074 */ | ||
if (typeof data !== 'string') { | ||
data = data.toString() | ||
} | ||
var pos = 0 | ||
this.write = function (data) { | ||
if (typeof data !== 'string') { | ||
data = data.toString() | ||
} | ||
var pos = 0 | ||
/* Anything from previous write()? */ | ||
if (remainder) { | ||
data = remainder + data | ||
pos += remainder.length | ||
remainder = null | ||
} | ||
/* Anything from previous write()? */ | ||
if (remainder) { | ||
data = remainder + data | ||
pos += remainder.length | ||
remainder = null | ||
} | ||
function endRecording() { | ||
if (typeof recordStart === 'number') { | ||
var recorded = data.slice(recordStart, pos) | ||
recordStart = undefined | ||
return recorded | ||
} | ||
} | ||
function endRecording () { | ||
if (typeof recordStart === 'number') { | ||
var recorded = data.slice(recordStart, pos) | ||
recordStart = undefined | ||
return recorded | ||
} | ||
} | ||
for(; pos < data.length; pos++) { | ||
var c = data.charCodeAt(pos) | ||
//console.log("state", state, "c", c, data[pos]) | ||
switch(state) { | ||
case STATE_TEXT: | ||
if (c === 60 /* < */) { | ||
var text = endRecording() | ||
if (text) { | ||
this.emit('text', unescapeXml(text)) | ||
} | ||
state = STATE_TAG_NAME | ||
recordStart = pos + 1 | ||
attrs = {} | ||
} | ||
break | ||
case STATE_TAG_NAME: | ||
if (c === 47 /* / */ && recordStart === pos) { | ||
recordStart = pos + 1 | ||
endTag = true | ||
} else if (c === 33 /* ! */ || c === 63 /* ? */) { | ||
recordStart = undefined | ||
state = STATE_IGNORE_TAG | ||
} else if (c <= 32 || c === 47 /* / */ || c === 62 /* > */) { | ||
tagName = endRecording() | ||
pos-- | ||
state = STATE_TAG | ||
} | ||
break | ||
case STATE_IGNORE_TAG: | ||
if (c === 62 /* > */) { | ||
state = STATE_TEXT | ||
} | ||
break | ||
case STATE_TAG: | ||
if (c === 62 /* > */) { | ||
this._handleTagOpening(endTag, tagName, attrs) | ||
tagName = undefined | ||
attrs = undefined | ||
endTag = undefined | ||
selfClosing = undefined | ||
state = STATE_TEXT | ||
recordStart = pos + 1 | ||
} else if (c === 47 /* / */) { | ||
selfClosing = true | ||
} else if (c > 32) { | ||
recordStart = pos | ||
state = STATE_ATTR_NAME | ||
} | ||
break | ||
case STATE_ATTR_NAME: | ||
if (c <= 32 || c === 61 /* = */) { | ||
attrName = endRecording() | ||
pos-- | ||
state = STATE_ATTR_EQ | ||
} | ||
break | ||
case STATE_ATTR_EQ: | ||
if (c === 61 /* = */) { | ||
state = STATE_ATTR_QUOT | ||
} | ||
break | ||
case STATE_ATTR_QUOT: | ||
if (c === 34 /* " */ || c === 39 /* ' */) { | ||
attrQuote = c | ||
state = STATE_ATTR_VALUE | ||
recordStart = pos + 1 | ||
} | ||
break | ||
case STATE_ATTR_VALUE: | ||
if (c === attrQuote) { | ||
var value = unescapeXml(endRecording()) | ||
attrs[attrName] = value | ||
attrName = undefined | ||
state = STATE_TAG | ||
} | ||
break | ||
for (; pos < data.length; pos++) { | ||
var c = data.charCodeAt(pos) | ||
// console.log("state", state, "c", c, data[pos]) | ||
switch (state) { | ||
case STATE_TEXT: | ||
if (c === 60 /* < */) { | ||
var text = endRecording() | ||
if (text) { | ||
this.emit('text', unescapeXml(text)) | ||
} | ||
} | ||
state = STATE_TAG_NAME | ||
recordStart = pos + 1 | ||
attrs = {} | ||
} | ||
break | ||
case STATE_TAG_NAME: | ||
if (c === 47 /* / */ && recordStart === pos) { | ||
recordStart = pos + 1 | ||
endTag = true | ||
} else if (c === 33 /* ! */ || c === 63 /* ? */) { | ||
recordStart = undefined | ||
state = STATE_IGNORE_TAG | ||
} else if (c <= 32 || c === 47 /* / */ || c === 62 /* > */) { | ||
tagName = endRecording() | ||
pos-- | ||
state = STATE_TAG | ||
} | ||
break | ||
case STATE_IGNORE_TAG: | ||
if (c === 62 /* > */) { | ||
state = STATE_TEXT | ||
} | ||
break | ||
case STATE_TAG: | ||
if (c === 62 /* > */) { | ||
this._handleTagOpening(endTag, tagName, attrs) | ||
tagName = undefined | ||
attrs = undefined | ||
endTag = undefined | ||
selfClosing = undefined | ||
state = STATE_TEXT | ||
recordStart = pos + 1 | ||
} else if (c === 47 /* / */) { | ||
selfClosing = true | ||
} else if (c > 32) { | ||
recordStart = pos | ||
state = STATE_ATTR_NAME | ||
} | ||
break | ||
case STATE_ATTR_NAME: | ||
if (c <= 32 || c === 61 /* = */) { | ||
attrName = endRecording() | ||
pos-- | ||
state = STATE_ATTR_EQ | ||
} | ||
break | ||
case STATE_ATTR_EQ: | ||
if (c === 61 /* = */) { | ||
state = STATE_ATTR_QUOT | ||
} | ||
break | ||
case STATE_ATTR_QUOT: | ||
if (c === 34 /* " */ || c === 39 /* ' */) { | ||
attrQuote = c | ||
state = STATE_ATTR_VALUE | ||
recordStart = pos + 1 | ||
} | ||
break | ||
case STATE_ATTR_VALUE: | ||
if (c === attrQuote) { | ||
var value = unescapeXml(endRecording()) | ||
attrs[attrName] = value | ||
attrName = undefined | ||
state = STATE_TAG | ||
} | ||
break | ||
} | ||
} | ||
if (typeof recordStart === 'number' && | ||
recordStart <= data.length) { | ||
remainder = data.slice(recordStart) | ||
recordStart = 0 | ||
} | ||
if (typeof recordStart === 'number' && | ||
recordStart <= data.length) { | ||
remainder = data.slice(recordStart) | ||
recordStart = 0 | ||
} | ||
/*var origEmit = this.emit | ||
this.emit = function() { | ||
} | ||
/* | ||
var origEmit = this.emit | ||
this.emit = function() { | ||
console.log('ltx', arguments) | ||
origEmit.apply(this, arguments) | ||
}*/ | ||
} | ||
*/ | ||
} | ||
inherits(SaxLtx, EventEmitter) | ||
SaxLtx.prototype.end = function (data) { | ||
if (data) { | ||
this.write(data) | ||
} | ||
SaxLtx.prototype.end = function(data) { | ||
if (data) { | ||
this.write(data) | ||
} | ||
/* Uh, yeah */ | ||
this.write = function() {} | ||
/* Uh, yeah */ | ||
this.write = function () {} | ||
} | ||
function unescapeXml(s) { | ||
return s. | ||
replace(/\&(amp|#38);/g, '&'). | ||
replace(/\&(lt|#60);/g, '<'). | ||
replace(/\&(gt|#62);/g, '>'). | ||
replace(/\&(quot|#34);/g, '"'). | ||
replace(/\&(apos|#39);/g, '\''). | ||
replace(/\&(nbsp|#160);/g, '\n') | ||
function unescapeXml (s) { | ||
return s | ||
.replace(/\&(amp|#38);/g, '&') | ||
.replace(/\&(lt|#60);/g, '<') | ||
.replace(/\&(gt|#62);/g, '>') | ||
.replace(/\&(quot|#34);/g, '"') | ||
.replace(/\&(apos|#39);/g, "'") | ||
.replace(/\&(nbsp|#160);/g, '\n') | ||
} | ||
@@ -1054,3 +1057,3 @@ | ||
},{}]},{},[4])(4) | ||
},{}]},{},[1])(1) | ||
}); |
{ | ||
"name": "ltx", | ||
"version": "2.0.1", | ||
"main": "./lib/index", | ||
"browser": "./lib/index-browserify", | ||
"description": "<xml for=\"node.js\" browserify=\"too\">", | ||
"version": "2.0.2", | ||
"description": "<xml for=\"JavaScript\">", | ||
"author": "Astro", | ||
@@ -33,21 +31,21 @@ "repository": "github:node-xmpp/ltx", | ||
"engine": "node", | ||
"scripts": { | ||
"preversion": "npm test", | ||
"webify": "browserify -s ltx index.js -o ltx.js", | ||
"unit": "vows --spec", | ||
"lint": "standard", | ||
"test": "npm run unit && npm run lint && npm run webify" | ||
}, | ||
"dependencies": { | ||
"inherits": "^2.0.1" | ||
}, | ||
"devDependencies": { | ||
"benchmark": "^1.0.0", | ||
"easysax": "^0.1.14", | ||
"eslint": "^1.3.1", | ||
"microtime": "^2.0.0", | ||
"node-expat": "^2.3.9", | ||
"node-expat": "^2.3.10", | ||
"node-xml": "^1.0.2", | ||
"sax": "^1.1.2", | ||
"vows": "^0.8.1" | ||
}, | ||
"scripts": { | ||
"webify": "browserify -s ltx lib/index.js -o ltx.js", | ||
"unit": "./node_modules/.bin/vows --spec", | ||
"lint": "./node_modules/.bin/eslint .", | ||
"test": "npm run unit && npm run lint && npm run webify" | ||
}, | ||
"dependencies": { | ||
"inherits": "^2.0.1" | ||
} | ||
} |
# Less-Than XML | ||
`<xml for=\"JavaScript\">` | ||
[![build status](https://img.shields.io/travis/node-xmpp/ltx/master.svg?style=flat-square)](https://travis-ci.org/node-xmpp/ltx/branches) | ||
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](http://standardjs.com/) | ||
* *Element:* any XML Element | ||
* Text nodes are Strings | ||
* Runs on node.js and browserify | ||
* Runs on Node.js and browsers | ||
## Build status | ||
[![Build Status](https://secure.travis-ci.org/node-xmpp/ltx.png)](http://travis-ci.org/node-xmpp/ltx) | ||
# Documentation | ||
@@ -15,3 +16,11 @@ | ||
# Test | ||
``` | ||
npm install -g standard browserify | ||
``` | ||
npm test | ||
## TODO | ||
@@ -18,0 +27,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
7
1812
34
52346
16