source: trip-planner-front/node_modules/critters/src/dom4.js@ eed0bf8

Last change on this file since eed0bf8 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 6.0 KB
RevLine 
[6a3a178]1/**
2 * Copyright 2018 Google LLC
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17// import parse5 from 'parse5';
18// import { parseDOM, DomUtils } from 'htmlparser2';
19import select from 'css-select';
20
21const { parseDOM, DomUtils } = require('htmlparser2');
22
23// htmlparser2 has a relatively DOM-like tree format, which we'll massage into a DOM elsewhere
24const treeAdapter = require('parse5-htmlparser2-tree-adapter');
25
26const PARSE5_OPTS = {
27 treeAdapter,
28};
29
30/**
31 * Parse HTML into a mutable, serializable DOM Document.
32 * The DOM implementation is an htmlparser2 DOM enhanced with basic DOM mutation methods.
33 * @param {String} html HTML to parse into a Document instance
34 */
35export function createDocument(html) {
36 // const document = parse5.parse(html, PARSE5_OPTS);
37 const document = parseDOM(html);
38
39 defineProperties(document, DocumentExtensions);
40
41 // Extend Element.prototype with DOM manipulation methods.
42 // const scratch = document.createElement('div');
43 // Get a reference to the base Node class - used by createTextNode()
44 // document.$$Node = scratch.constructor;
45 // const elementProto = Object.getPrototypeOf(scratch);
46 // defineProperties(elementProto, ElementExtensions);
47 // elementProto.ownerDocument = document;
48
49 return document;
50}
51
52/**
53 * Serialize a Document to an HTML String
54 * @param {Document} document A Document, such as one created via `createDocument()`
55 */
56export function serializeDocument(document) {
57 return DomUtils.getOuterHTML(document);
58}
59
60/**
61 * Methods and descriptors to mix into Element.prototype
62 */
63const ElementExtensions = {
64 /** @extends htmlparser2.Element.prototype */
65
66 nodeName: {
67 get() {
68 return this.tagName.toUpperCase();
69 },
70 },
71
72 id: reflectedProperty('id'),
73
74 className: reflectedProperty('class'),
75 parentNode: {
76 get() {
77 if (this.parent) defineProperties(this.parent, ElementExtensions);
78 return this.parent;
79 },
80 },
81
82 insertBefore(child, referenceNode) {
83 if (!referenceNode) return this.appendChild(child);
84 DomUtils.prepend(referenceNode, child);
85 return child;
86 },
87
88 appendChild(child) {
89 DomUtils.appendChild(this, child);
90 return child;
91 },
92
93 removeChild(child) {
94 DomUtils.removeElement(child);
95 },
96
97 remove() {
98 DomUtils.removeElement(this);
99 },
100
101 textContent: {
102 get() {
103 return DomUtils.getText(this);
104 },
105
106 set(text) {
107 this.children = [];
108 DomUtils.appendChild(this, createTextNode(text));
109 },
110 },
111
112 setAttribute(name, value) {
113 if (this.attribs == null) this.attribs = {};
114 if (value == null) value = '';
115 this.attribs[name] = value;
116 },
117
118 removeAttribute(name) {
119 if (this.attribs != null) {
120 delete this.attribs[name];
121 }
122 },
123
124 getAttribute(name) {
125 return this.attribs != null && this.attribs[name];
126 },
127
128 hasAttribute(name) {
129 return this.attribs != null && this.attribs[name] != null;
130 },
131
132 getAttributeNode(name) {
133 const value = this.getAttribute(name);
134 if (value != null) return { specified: true, value };
135 },
136};
137
138/**
139 * Methods and descriptors to mix into the global document instance
140 * @private
141 */
142const DocumentExtensions = {
143 /** @extends htmlparser2.Document.prototype */
144
145 // document is just an Element in htmlparser2, giving it a nodeType of ELEMENT_NODE.
146 // TODO: verify if these are needed for css-select
147 nodeType: {
148 get() {
149 return 9;
150 },
151 },
152
153 contentType: {
154 get() {
155 return 'text/html';
156 },
157 },
158
159 nodeName: {
160 get() {
161 return '#document';
162 },
163 },
164
165 documentElement: {
166 get() {
167 // Find the first <html> element within the document
168 return this.filter(
169 (child) => String(child.tagName).toLowerCase() === 'html'
170 );
171 },
172 },
173
174 compatMode: {
175 get() {
176 const compatMode = {
177 'no-quirks': 'CSS1Compat',
178 quirks: 'BackCompat',
179 'limited-quirks': 'CSS1Compat',
180 };
181 return compatMode[treeAdapter.getDocumentMode(this)];
182 },
183 },
184
185 body: {
186 get() {
187 return this.querySelector('body');
188 },
189 },
190
191 createElement(tagName) {
192 const node = {
193 type: tagName === 'script' || tagName === 'style' ? tagName : 'tag',
194 name: tagName,
195 attribs: [],
196 children: [],
197 parent: null,
198 prev: null,
199 next: null,
200 };
201 defineProperties(node, ElementExtensions);
202 return node;
203 },
204
205 querySelector(sel) {
206 if (sel === ':root') {
207 return this.type === 'root';
208 }
209
210 const res = select.selectOne(sel, this.documentElement);
211 if (res) defineProperties(res, ElementExtensions);
212 return res;
213 },
214
215 querySelectorAll(sel) {
216 if (sel === ':root') {
217 return this.type === 'root';
218 }
219
220 const res = select(sel, this.documentElement);
221
222 res.forEach((r) => {
223 if (r) defineProperties(r, ElementExtensions);
224 });
225 return res;
226 },
227};
228
229/**
230 * Essentially `Object.defineProperties()`, except function values are assigned as value descriptors for convenience.
231 * @private
232 */
233function defineProperties(obj, properties) {
234 for (const i in properties) {
235 const value = properties[i];
236 Object.defineProperty(
237 obj,
238 i,
239 typeof value === 'function' ? { value } : value
240 );
241 }
242}
243
244/**
245 * Create a property descriptor defining a getter/setter pair alias for a named attribute.
246 * @private
247 */
248function reflectedProperty(attributeName) {
249 return {
250 get() {
251 return this.getAttribute(attributeName);
252 },
253 set(value) {
254 this.setAttribute(attributeName, value);
255 },
256 };
257}
258
259function createTextNode(text) {
260 return parseDOM(text)[0];
261}
Note: See TracBrowser for help on using the repository browser.