1b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik'use strict';
2b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
3b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikvar Doctype = require('../common/doctype');
4b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
5b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik//Conversion tables for DOM Level1 structure emulation
6b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikvar nodeTypes = {
7b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    element: 1,
8b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    text: 3,
9b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    cdata: 4,
10b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    comment: 8
11b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
12b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
13b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikvar nodePropertyShorthands = {
14b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    tagName: 'name',
15b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    childNodes: 'children',
16b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    parentNode: 'parent',
17b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    previousSibling: 'prev',
18b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    nextSibling: 'next',
19b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    nodeValue: 'data'
20b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
21b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
22b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik//Node
23b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikvar Node = function (props) {
24b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    for (var key in props) {
25b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if (props.hasOwnProperty(key))
26b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            this[key] = props[key];
27b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    }
28b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
29b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
30b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikNode.prototype = {
31b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    get firstChild() {
32b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        var children = this.children;
33b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return children && children[0] || null;
34b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    },
35b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
36b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    get lastChild() {
37b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        var children = this.children;
38b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return children && children[children.length - 1] || null;
39b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    },
40b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
41b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    get nodeType() {
42b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        return nodeTypes[this.type] || nodeTypes.element;
43b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    }
44b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
45b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
46b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikObject.keys(nodePropertyShorthands).forEach(function (key) {
47b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    var shorthand = nodePropertyShorthands[key];
48b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
49b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    Object.defineProperty(Node.prototype, key, {
50b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        get: function () {
51b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            return this[shorthand] || null;
52b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        },
53b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        set: function (val) {
54b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            this[shorthand] = val;
55b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            return val;
56b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        }
57b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    });
58b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik});
59b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
60b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
61b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik//Node construction
62b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.createDocument =
63b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.createDocumentFragment = function () {
64b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return new Node({
65b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        type: 'root',
66b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        name: 'root',
67b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        parent: null,
68b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        prev: null,
69b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        next: null,
70b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        children: []
71b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    });
72b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
73b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
74b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.createElement = function (tagName, namespaceURI, attrs) {
75b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    var attribs = {},
76b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        attribsNamespace = {},
77b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        attribsPrefix = {};
78b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
79b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    for (var i = 0; i < attrs.length; i++) {
80b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        var attrName = attrs[i].name;
81b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
82b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        attribs[attrName] = attrs[i].value;
83b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        attribsNamespace[attrName] = attrs[i].namespace;
84b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        attribsPrefix[attrName] = attrs[i].prefix;
85b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    }
86b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
87b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return new Node({
88b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        type: tagName === 'script' || tagName === 'style' ? tagName : 'tag',
89b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        name: tagName,
90b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        namespace: namespaceURI,
91b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        attribs: attribs,
92b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'x-attribsNamespace': attribsNamespace,
93b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        'x-attribsPrefix': attribsPrefix,
94b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        children: [],
95b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        parent: null,
96b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        prev: null,
97b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        next: null
98b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    });
99b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
100b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
101b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.createCommentNode = function (data) {
102b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return new Node({
103b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        type: 'comment',
104b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        data: data,
105b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        parent: null,
106b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        prev: null,
107b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        next: null
108b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    });
109b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
110b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
111b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikvar createTextNode = function (value) {
112b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return new Node({
113b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        type: 'text',
114b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        data: value,
115b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        parent: null,
116b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        prev: null,
117b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        next: null
118b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    });
119b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
120b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
121b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
122b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik//Tree mutation
123b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.setDocumentType = function (document, name, publicId, systemId) {
124b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    var data = Doctype.serializeContent(name, publicId, systemId),
125b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        doctypeNode = null;
126b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
127b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    for (var i = 0; i < document.children.length; i++) {
128b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if (document.children[i].type === 'directive' && document.children[i].name === '!doctype') {
129b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            doctypeNode = document.children[i];
130b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            break;
131b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        }
132b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    }
133b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
134b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if (doctypeNode) {
135b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        doctypeNode.data = data;
136b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        doctypeNode['x-name'] = name;
137b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        doctypeNode['x-publicId'] = publicId;
138b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        doctypeNode['x-systemId'] = systemId;
139b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    }
140b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
141b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else {
142b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        appendChild(document, new Node({
143b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            type: 'directive',
144b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            name: '!doctype',
145b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            data: data,
146b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            'x-name': name,
147b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            'x-publicId': publicId,
148b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            'x-systemId': systemId
149b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        }));
150b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    }
151b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
152b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
153b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
154b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.setQuirksMode = function (document) {
155b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    document.quirksMode = true;
156b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
157b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
158b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.isQuirksMode = function (document) {
159b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return document.quirksMode;
160b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
161b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
162b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikvar appendChild = exports.appendChild = function (parentNode, newNode) {
163b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    var prev = parentNode.children[parentNode.children.length - 1];
164b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
165b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if (prev) {
166b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        prev.next = newNode;
167b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        newNode.prev = prev;
168b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    }
169b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
170b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    parentNode.children.push(newNode);
171b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    newNode.parent = parentNode;
172b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
173b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
174b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikvar insertBefore = exports.insertBefore = function (parentNode, newNode, referenceNode) {
175b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    var insertionIdx = parentNode.children.indexOf(referenceNode),
176b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        prev = referenceNode.prev;
177b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
178b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if (prev) {
179b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        prev.next = newNode;
180b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        newNode.prev = prev;
181b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    }
182b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
183b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    referenceNode.prev = newNode;
184b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    newNode.next = referenceNode;
185b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
186b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    parentNode.children.splice(insertionIdx, 0, newNode);
187b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    newNode.parent = parentNode;
188b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
189b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
190b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.detachNode = function (node) {
191b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if (node.parent) {
192b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        var idx = node.parent.children.indexOf(node),
193b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            prev = node.prev,
194b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            next = node.next;
195b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
196b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        node.prev = null;
197b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        node.next = null;
198b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
199b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if (prev)
200b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            prev.next = next;
201b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
202b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if (next)
203b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            next.prev = prev;
204b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
205b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        node.parent.children.splice(idx, 1);
206b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        node.parent = null;
207b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    }
208b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
209b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
210b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.insertText = function (parentNode, text) {
211b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    var lastChild = parentNode.children[parentNode.children.length - 1];
212b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
213b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if (lastChild && lastChild.type === 'text')
214b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        lastChild.data += text;
215b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else
216b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        appendChild(parentNode, createTextNode(text));
217b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
218b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
219b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.insertTextBefore = function (parentNode, text, referenceNode) {
220b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    var prevNode = parentNode.children[parentNode.children.indexOf(referenceNode) - 1];
221b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
222b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    if (prevNode && prevNode.type === 'text')
223b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        prevNode.data += text;
224b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    else
225b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        insertBefore(parentNode, createTextNode(text), referenceNode);
226b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
227b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
228b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.adoptAttributes = function (recipientNode, attrs) {
229b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    for (var i = 0; i < attrs.length; i++) {
230b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        var attrName = attrs[i].name;
231b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
232b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if (typeof recipientNode.attribs[attrName] === 'undefined') {
233b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            recipientNode.attribs[attrName] = attrs[i].value;
234b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            recipientNode['x-attribsNamespace'][attrName] = attrs[i].namespace;
235b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            recipientNode['x-attribsPrefix'][attrName] = attrs[i].prefix;
236b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        }
237b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    }
238b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
239b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
240b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
241b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik//Tree traversing
242b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.getFirstChild = function (node) {
243b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return node.children[0];
244b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
245b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
246b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.getChildNodes = function (node) {
247b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return node.children;
248b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
249b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
250b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.getParentNode = function (node) {
251b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return node.parent;
252b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
253b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
254b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.getAttrList = function (node) {
255b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    var attrList = [];
256b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
257b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    for (var name in node.attribs) {
258b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        if (node.attribs.hasOwnProperty(name)) {
259b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            attrList.push({
260b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                name: name,
261b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                value: node.attribs[name],
262b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                namespace: node['x-attribsNamespace'][name],
263b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik                prefix: node['x-attribsPrefix'][name]
264b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik            });
265b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik        }
266b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    }
267b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
268b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return attrList;
269b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
270b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
271b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
272b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik//Node data
273b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.getTagName = function (element) {
274b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return element.name;
275b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
276b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
277b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.getNamespaceURI = function (element) {
278b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return element.namespace;
279b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
280b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
281b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.getTextNodeContent = function (textNode) {
282b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return textNode.data;
283b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
284b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
285b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.getCommentNodeContent = function (commentNode) {
286b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return commentNode.data;
287b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
288b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
289b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.getDocumentTypeNodeName = function (doctypeNode) {
290b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return doctypeNode['x-name'];
291b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
292b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
293b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.getDocumentTypeNodePublicId = function (doctypeNode) {
294b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return doctypeNode['x-publicId'];
295b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
296b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
297b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.getDocumentTypeNodeSystemId = function (doctypeNode) {
298b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return doctypeNode['x-systemId'];
299b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
300b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
301b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
302b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik//Node types
303b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.isTextNode = function (node) {
304b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return node.type === 'text';
305b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
306b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
307b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.isCommentNode = function (node) {
308b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return node.type === 'comment';
309b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
310b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
311b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.isDocumentTypeNode = function (node) {
312b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return node.type === 'directive' && node.name === '!doctype';
313b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
314b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik
315b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexports.isElementNode = function (node) {
316b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik    return !!node.attribs;
317b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik};
318