1 | "use strict";
|
2 |
|
3 | const cheerio = require("cheerio");
|
4 |
|
5 | module.exports = function DocumentFragment(Element, templateElement) {
|
6 | const $ = cheerio.load("", {decodeEntities: false});
|
7 | const $body = $("body");
|
8 | const loaded = [];
|
9 |
|
10 | if (templateElement) {
|
11 | $body.html(getContent(templateElement.$elm));
|
12 | }
|
13 |
|
14 | const fragment = {
|
15 | $elm: $body,
|
16 | _getElement: getElement,
|
17 | _getContent() {
|
18 | return getContent($body);
|
19 | },
|
20 | _clone: clone,
|
21 | querySelector,
|
22 | querySelectorAll,
|
23 | appendChild,
|
24 | };
|
25 |
|
26 | Object.setPrototypeOf(fragment, DocumentFragment.prototype);
|
27 | return fragment;
|
28 |
|
29 | function clone(deep) {
|
30 | return DocumentFragment(Element, deep && {$elm: $body});
|
31 | }
|
32 |
|
33 | function getElement($elm) {
|
34 | if ($elm === $) return fragment;
|
35 | if (!$elm.length) return;
|
36 |
|
37 | let mockElement = loaded.find((mockedElm) => mockedElm.$elm[0] === $elm[0]);
|
38 | if (mockElement) {
|
39 | return mockElement;
|
40 | }
|
41 |
|
42 | mockElement = Element(fragment, $elm);
|
43 |
|
44 | loaded.push(mockElement);
|
45 | return mockElement;
|
46 | }
|
47 |
|
48 | function getContent($elm) {
|
49 | let content = "";
|
50 | $elm.contents().each((_, elm) => {
|
51 | content += $.html(elm, {decodeEntities: true});
|
52 | });
|
53 |
|
54 | return content;
|
55 | }
|
56 |
|
57 | function querySelector(selector) {
|
58 | return getElement($body.find(selector).eq(0)) || null;
|
59 | }
|
60 |
|
61 | function querySelectorAll(selector) {
|
62 | return $body.find(selector).map((_, elm) => getElement($(elm)));
|
63 | }
|
64 |
|
65 | function appendChild(child) {
|
66 | $body.append(child.$elm);
|
67 | }
|
68 | };
|