2023-09-26 22:31:11 +02:00
|
|
|
const SpaccDotWeb = ((args) => { //////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
let windowObject, documentObject;
|
|
|
|
let Lib = {};
|
2023-09-27 00:49:37 +02:00
|
|
|
let isBuildingApp = false;
|
2023-09-29 00:19:44 +02:00
|
|
|
let __scriptname;
|
2023-09-26 22:31:11 +02:00
|
|
|
|
|
|
|
const platformIsNode = (typeof module === 'object' && typeof module.exports === 'object');
|
|
|
|
const platformIsBrowser = (typeof window !== 'undefined' && typeof window.document !== 'undefined');
|
|
|
|
|
|
|
|
if (platformIsNode) {
|
|
|
|
Lib.fs = require('fs');
|
2023-09-29 00:19:44 +02:00
|
|
|
Lib.crypto = require('crypto');
|
2023-09-27 00:49:37 +02:00
|
|
|
Lib.childProcess = require('child_process');
|
2023-09-26 22:31:11 +02:00
|
|
|
Lib.jsdom = require('jsdom');
|
2023-09-29 00:19:44 +02:00
|
|
|
__scriptname = __filename.split('/').slice(-1)[0];
|
2023-09-26 22:31:11 +02:00
|
|
|
windowObject = new Lib.jsdom.JSDOM().window;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (platformIsBrowser) {
|
|
|
|
windowObject = window;
|
|
|
|
};
|
|
|
|
|
|
|
|
documentObject = windowObject.document;
|
|
|
|
|
|
|
|
|
|
|
|
const SpaccDotWeb = ((args) => { //////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
let SpaccDotWeb = {};
|
|
|
|
|
2023-09-27 00:49:37 +02:00
|
|
|
if (platformIsNode) {
|
2023-09-29 00:19:44 +02:00
|
|
|
SpaccDotWeb.AppBuildStandalone = (opts) => {
|
2023-09-27 00:49:37 +02:00
|
|
|
isBuildingApp = true;
|
2023-09-29 00:19:44 +02:00
|
|
|
opts ||= {};
|
|
|
|
opts.Page ||= 'index.html';
|
|
|
|
opts.Modules && !opts.Modules.includes('Main') && (opts.Modules = [...opts.Modules, 'Main']);
|
2023-09-26 22:31:11 +02:00
|
|
|
|
2023-09-29 00:19:44 +02:00
|
|
|
Lib.fs.mkdirSync(`${__dirname}/Build/App-${opts.Page}`, { recursive: true });
|
|
|
|
let htmlIndex = Lib.fs.readFileSync(opts.Page, 'utf8');
|
2023-09-26 22:31:11 +02:00
|
|
|
|
2023-09-27 00:49:37 +02:00
|
|
|
windowObject = new Lib.jsdom.JSDOM(htmlIndex).window;
|
|
|
|
documentObject = windowObject.document;
|
2023-09-26 22:31:11 +02:00
|
|
|
|
2023-09-29 00:19:44 +02:00
|
|
|
DomSetup(opts.Modules);
|
|
|
|
Lib.fs.writeFileSync(`${__dirname}/Build/App-${opts.Page}/Full.html`, `<!DOCTYPE html>${documentObject.documentElement.outerHTML}`);
|
2023-09-26 22:31:11 +02:00
|
|
|
|
2023-09-27 00:49:37 +02:00
|
|
|
isBuildingApp = false;
|
2023-09-29 00:19:44 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
SpaccDotWeb.LibBuild = () => {
|
|
|
|
Lib.fs.mkdirSync(`${__dirname}/Build/Assets.tmp`, { recursive: true });
|
|
|
|
let uptodate = true;
|
|
|
|
const compiledPath = `${__dirname}/Build/SpaccDotWeb.js`;
|
|
|
|
const minifiedPath = `${__dirname}/Build/SpaccDotWeb.min.js`;
|
|
|
|
const hashPath = `${__dirname}/Build/SpaccDotWeb.js.hash`;
|
|
|
|
const hashOld = (Lib.fs.existsSync(hashPath) && Lib.fs.readFileSync(hashPath, 'utf8'));
|
|
|
|
const hashNew = Lib.crypto.createHash('sha256').update(Lib.fs.readFileSync(__filename, 'utf8')).digest('hex');
|
|
|
|
if (!Lib.fs.existsSync(compiledPath) || !Lib.fs.existsSync(minifiedPath) || !(hashOld === hashNew)) {
|
|
|
|
uptodate = false;
|
|
|
|
Lib.fs.writeFileSync(hashPath, hashNew);
|
|
|
|
Lib.fs.writeFileSync(compiledPath, Lib.childProcess.execSync(`cat "${__filename}" | npx babel -f "${__scriptname}"`));
|
|
|
|
Lib.fs.writeFileSync(minifiedPath, Lib.childProcess.execSync(`cat "${compiledPath}" | npx uglifyjs`));
|
|
|
|
};
|
|
|
|
uptodate && console.log('Library is up-to-date.');
|
|
|
|
return { compiledText: Lib.fs.readFileSync(compiledPath, 'utf8'), minified: Lib.fs.readFileSync(minifiedPath, 'utf8') };
|
2023-09-27 00:49:37 +02:00
|
|
|
};
|
2023-09-26 22:31:11 +02:00
|
|
|
};
|
|
|
|
|
2023-09-27 00:49:37 +02:00
|
|
|
SpaccDotWeb.AppInit = function AppInit(){
|
2023-09-26 22:31:11 +02:00
|
|
|
try {
|
2023-09-27 00:49:37 +02:00
|
|
|
DomSetup();
|
2023-09-29 00:19:44 +02:00
|
|
|
} catch(err) { console.log(err) };
|
2023-09-26 22:31:11 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
//SpaccDotWeb.Make = () => {};
|
|
|
|
|
|
|
|
SpaccDotWeb.Create = (tag, attrs) => {
|
|
|
|
let elem = documentObject.createElement(tag);
|
2023-09-27 00:49:37 +02:00
|
|
|
for (const key in attrs) {
|
|
|
|
elem[key] = attrs[key];
|
|
|
|
};
|
2023-09-26 22:31:11 +02:00
|
|
|
return elem;
|
|
|
|
};
|
|
|
|
|
2023-09-27 00:49:37 +02:00
|
|
|
SpaccDotWeb.Select = (query) => {
|
2023-09-26 22:31:11 +02:00
|
|
|
let elem = documentObject.querySelector(query);
|
|
|
|
elem && (elem.Insert = elem.appendChild);
|
|
|
|
return elem;
|
|
|
|
};
|
|
|
|
|
2023-09-27 00:49:37 +02:00
|
|
|
const AppMetaGet = () => JSON.parse(SpaccDotWeb.Select('#Meta').innerHTML);
|
2023-09-26 22:31:11 +02:00
|
|
|
|
2023-09-29 00:19:44 +02:00
|
|
|
const DomMakeBase = (Modules) => {
|
2023-09-26 22:31:11 +02:00
|
|
|
const meta = AppMetaGet();
|
2023-09-27 00:49:37 +02:00
|
|
|
|
2023-09-26 22:31:11 +02:00
|
|
|
const htmlFrags = {
|
|
|
|
Title: (meta.Name ? `<title>${meta.Name}</title><meta property="og:title" content="${meta.Name}"/>` : ''),
|
|
|
|
Description: (meta.Description ? `<meta name="description" content="${meta.Description}"/><meta property="og:description" content="${meta.Description}"/>` : ''),
|
|
|
|
Uri: (meta.Uri ? `<link rel="canonical" href="${meta.Uri}"/><meta property="og:url" content="${meta.Uri}"/>` : '')
|
|
|
|
};
|
|
|
|
|
|
|
|
let scripts = '';
|
|
|
|
|
2023-09-29 00:19:44 +02:00
|
|
|
if (isBuildingApp) {
|
|
|
|
scripts += `<scr`+`ipt src="http://cdn.jsdelivr.net/npm/core-js-bundle/minified.min.js"></scr`+`ipt>`;
|
2023-09-27 00:49:37 +02:00
|
|
|
scripts += `<scr`+`ipt src="https://cdn.jsdelivr.net/npm/core-js-bundle/minified.min.js"></scr`+`ipt>`;
|
2023-09-29 00:19:44 +02:00
|
|
|
scripts += `<scr`+`ipt>${SpaccDotWeb.LibBuild().minified}</scr`+`ipt>`;
|
2023-09-26 22:31:11 +02:00
|
|
|
for (const elem of documentObject.querySelectorAll('script[module]')) {
|
2023-09-29 00:19:44 +02:00
|
|
|
if (!Modules || (Modules && Modules.includes(elem.getAttribute('module')))) {
|
|
|
|
if (elem.getAttribute('src')) {
|
|
|
|
scripts += `<scr`+`ipt src="${elem.getAttribute('src')}"></scr`+`ipt>`
|
|
|
|
} else {
|
|
|
|
const tmpHash = Lib.crypto.createHash('sha256').update(elem.innerHTML).digest('hex');
|
|
|
|
const tmpPath = `${__dirname}/Build/Assets.tmp/${tmpHash}.js`;
|
|
|
|
Lib.fs.writeFileSync(tmpPath, elem.innerHTML);
|
|
|
|
scripts += `<scr`+`ipt>${Lib.childProcess.execSync(`cat "${tmpPath}" | npx babel -f "${tmpHash}.js" | npx uglifyjs`)}</scr`+`ipt>`;
|
|
|
|
};
|
|
|
|
};
|
2023-09-26 22:31:11 +02:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
return {
|
|
|
|
head: `
|
2023-09-27 00:49:37 +02:00
|
|
|
<meta charset="utf-8"/>
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
|
|
${htmlFrags.Title}
|
|
|
|
${htmlFrags.Description}
|
|
|
|
${htmlFrags.Uri}
|
2023-09-26 22:31:11 +02:00
|
|
|
`,
|
|
|
|
body: `<div id="App"></div>${scripts}`,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-09-29 00:19:44 +02:00
|
|
|
const DomSetup = (Modules) => {
|
2023-09-26 22:31:11 +02:00
|
|
|
const doctypeNew = documentObject.implementation.createHTMLDocument().doctype;
|
|
|
|
windowObject.document.doctype
|
|
|
|
? documentObject.replaceChild(doctypeNew, documentObject.doctype)
|
|
|
|
: documentObject.insertBefore(doctypeNew, documentObject.childNodes[0]);
|
2023-09-29 00:19:44 +02:00
|
|
|
const domBase = DomMakeBase(Modules);
|
2023-09-26 22:31:11 +02:00
|
|
|
documentObject.write(domBase.head + domBase.body);
|
|
|
|
documentObject.head.innerHTML = domBase.head;
|
|
|
|
documentObject.body.innerHTML = domBase.body;
|
|
|
|
};
|
|
|
|
|
|
|
|
return SpaccDotWeb;
|
|
|
|
|
|
|
|
|
|
|
|
})(); /////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
2023-09-27 00:49:37 +02:00
|
|
|
platformIsBrowser && (window.SpaccDotWeb = SpaccDotWeb);
|
2023-09-26 22:31:11 +02:00
|
|
|
platformIsNode && (console.log(eval(process.argv.slice(-1)[0])));
|
|
|
|
|
|
|
|
return SpaccDotWeb;
|
|
|
|
|
|
|
|
|
|
|
|
})(); /////////////////////////////////////////////////////////////////////////
|