commit 682eefa6e101ef0e6b873cc1789dff863bf4c359 Author: german Date: Wed May 27 19:37:21 2026 +0400 init diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/examples/simple/cat.jpg b/examples/simple/cat.jpg new file mode 100644 index 0000000..bad273c Binary files /dev/null and b/examples/simple/cat.jpg differ diff --git a/examples/simple/index.html b/examples/simple/index.html new file mode 100644 index 0000000..15cba2e --- /dev/null +++ b/examples/simple/index.html @@ -0,0 +1,40 @@ + + + + + + + jServe basic example + + + + + + + + + + + diff --git a/examples/simple/index.js b/examples/simple/index.js new file mode 100644 index 0000000..ec3c41a --- /dev/null +++ b/examples/simple/index.js @@ -0,0 +1,31 @@ +(() => { + const server = new jServer(); + + const core = document.getElementById("core"); + const lib = document.getElementById("lib"); + + server.isolate(core); + server.isolate(lib); + + (async () => { + const text = "Hello, world! Please wait 5 seconds"; + const script = "alert('Hello, world!');"; + + const url = String("./main_page.html"); + + const response = await fetch(url); + + if (response.ok) { + const html = await response.text(); + + const elem = await server.index({ + 'text' : text, + 'script' : script + }).element(html); + + setTimeout(() => elem.text = "Welcome", 5000); + } else { + alert("Ошибка HTTP: " + response.status); + } + })(); +})(); \ No newline at end of file diff --git a/examples/simple/main_page.html b/examples/simple/main_page.html new file mode 100644 index 0000000..8c13354 --- /dev/null +++ b/examples/simple/main_page.html @@ -0,0 +1,51 @@ + + + + + + + jServe basic example + + + + + + + + + +

+
+ + + + + + + + + + + diff --git a/src/js/jServer.js b/src/js/jServer.js new file mode 100644 index 0000000..7cce07d --- /dev/null +++ b/src/js/jServer.js @@ -0,0 +1,250 @@ +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)); + } +} \ No newline at end of file