let __JIsolate__ = new Array(); let __JSession__ = new String(); class jComponent { constructor(elems) { if (typeof elems !== "object") { throw new TypeError("Elements must be objects"); } this._elems = elems; } _proxyWindow() { return undefined; } _proxy_elems(obj) { const __Entr__ = this; return new Proxy(obj, new class { // TODO: Доделать получение данных set(target, prop, val) { if (target[prop] === val) { return true; } val = String(val); (() => { const elem = document .documentElement .querySelector( `[data-jserver-name-${__JSession__}="${prop}"]` ); const type = elem.getAttribute( `data-jserver-type-${__JSession__}` ); if (__Entr__._test_html_or_xml(type)) { elem.innerHTML = val; } else { elem.textContent = val; } })(); return Reflect.set(target, prop, val); } }); } _test_html_or_xml(type) { if ( type === "text/html" || type === "text/xml" || type === "application/xml" ) { return true; } return false; } _get_session_key(doc) { // ? Is this code efficient or just beautiful? return ( // ! Step 0: Create lambda (() => { let key = []; return ((key = ( // ! Step 1: get document doc.documentElement.innerHTML // ! Step 2: analize api tokens .match( //gi))) === null ? [] : key); })() // ! Step 3: search hex keys and prefixs .map( elem => elem.match(/:\s*?[ABCDEFabcdef1234567890]+/i)[0]) // ! Step 4: search hex keys .map( elem => elem.match(/[ABCDEFabcdef1234567890]+/i)[0]) ); } async element(html) { return new Promise((resolve, reject) => { try { this._proxyWindow(); if (typeof html !== "string") { throw new TypeError("HTML must be string!"); } const parser = new DOMParser(); const s = parser.parseFromString(html, "text/html"); const key = this._get_session_key(s); if (key.length > 0) { __JSession__ = key[key.length - 1]; } let objs = s.querySelectorAll("ref"); const test_html_or_xml = this._test_html_or_xml; function ref_test(g) { return String(g.parentNode.tagName).toLowerCase() === "ref"; } for (let val of objs) { const f = val.children; let type = val.getAttribute("type"); const name = val.getAttribute("name"); if (type === null) type = "text/plain"; if (name === null) { throw new TypeError(" tag hasn't attribute \"name\""); } if (f.length === 0) { if (test_html_or_xml(type)) { val.innerHTML = String(this._elems[name]); } else { val.textContent = String(this._elems[name]); } val.outerHTML = val.innerHTML; continue; } let l_inner = ""; if (test_html_or_xml(type)) { l_inner = "innerHTML"; } else { l_inner = "textContent"; } for (let g of f) { g.setAttribute('data-jserver-name-' + __JSession__, name); g.setAttribute('data-jserver-type-' + __JSession__, type); g[l_inner] = String(this._elems[name]); } val.outerHTML = val.innerHTML; } const head = this._createElement(document, 'head'); const body = this._createElement(document, 'body'); const S_head = this._createElement(s, 'head'); const S_body = this._createElement(s, 'body'); this._copyHTML(head, S_head, null); this._copyHTML(body, S_body, null); this._execAllScripts(document); this._elems = this._proxy_elems(this._elems); } catch (e) { reject(e); return; } resolve(this._elems); }); } _is_node_isolated(val) { for (let g of __JIsolate__) { if (val.isEqualNode(g)) { return true; } } return false; } _execAllScripts(doc) { const f = doc.querySelectorAll('script'); for (let u of f) { if (this._is_node_isolated(u)) continue; if (u.hasAttribute('src')) { u.copyAttributes = function (target) { let source = this; Array.from(source.attributes).forEach(attribute => { target.setAttribute(attribute.nodeName, attribute.nodeValue); }); } const g = doc.createElement('script'); u.copyAttributes(g); u.remove(); doc.body.append(g); } const fn = new Function('window', 'document', u.textContent); fn(window, document); } } _copyHTML(to, from, added) { const elems = to.querySelectorAll("*"); for (let val of elems) { if (!this._is_node_isolated(val)) { val.remove(); } } let f = ""; if (added !== null && typeof added === "string") { f = added; } to.insertAdjacentHTML('afterbegin', from.innerHTML + f); } _createElement(g, name) { let main_head = g.querySelector(name); if (main_head === null) { main_head = g.createElement(name); g.append(main_head); } return main_head; } } class jServer { _generateHexString(length) { var ret = ""; while (ret.length < length) { ret += Math.random().toString(16).substring(2); } return ret.substring(0, length); } constructor() { __JSession__ = this._generateHexString(8); } index(elems) { return new jComponent(elems); } isolate(elem) { __JIsolate__.push(Object(elem)); } }