Alt. updates; Build system tweaks

This commit is contained in:
octospacc 2024-09-14 23:01:50 +02:00
parent 9b23a57eeb
commit 9a20834ac0
7 changed files with 759 additions and 698 deletions

View File

@ -1,3 +1,4 @@
#!/bin/sh #!/bin/sh
node ./SpaccDotWeb.js 'SpaccDotWeb.LibBuild()' for file in ./SpaccDotWeb*.js
node ./SpaccDotWeb.Build.js 'BuildScriptFile("SpaccDotWeb.Alt.js")' do node ./SpaccDotWeb.Build.js "BuildScriptFile('${file}')"
done

View File

@ -3,13 +3,17 @@
SpaccDotWeb.AppInit = (meta) => { SpaccDotWeb.AppInit = (meta) => {
// ... load meta from argument or page element and add to object // ... load meta from argument or page element and add to object
return SpaccDotWeb; return { ...SpaccDotWeb,
} LocalStorage: (key, value) => SpaccDotWeb.LocalStorage(`${meta.uuid}/v1`, key, value),
};
};
SpaccDotWeb.Sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); SpaccDotWeb.LocalStorage = (prefix, key, value) => JSON.parse(
localStorage[value !== undefined ? 'setItem' : 'getItem'](
`${prefix}/${key}`, JSON.stringify(value)) || null);
SpaccDotWeb.RequireScript = (src, type) => { SpaccDotWeb.RequireScript = (src, type) => {
return new Promise((resolve) => { return (new Promise((resolve) => {
const scriptElem = document.createElement('script'); const scriptElem = document.createElement('script');
//if (type) { //if (type) {
// scriptElem.type = type; // scriptElem.type = type;
@ -19,39 +23,52 @@
}; };
scriptElem.src = src; scriptElem.src = src;
document.body.appendChild(scriptElem); document.body.appendChild(scriptElem);
}); }));
} };
// .RequireScripts = (...) => {} // .RequireScripts = (...) => {}
SpaccDotWeb.ShowModal = async (params) => { SpaccDotWeb.ShowModal = async (params) => {
// TODO: delete dialogs from DOM after use (garbage collect)? // TODO: delete dialogs from DOM after use (garbage collect)?
if (!window.HTMLDialogElement && !window.dialogPolyfill) { if (!window.HTMLDialogElement && !window.dialogPolyfill) {
// TODO include in dependencies, don't load from external server
await SpaccDotWeb.RequireScript('https://googlechrome.github.io/dialog-polyfill/dist/dialog-polyfill.js'); await SpaccDotWeb.RequireScript('https://googlechrome.github.io/dialog-polyfill/dist/dialog-polyfill.js');
} }
let output; let output;
if (typeof(params) === 'string') { if (typeof(params) === 'string') {
params = { label: params } params = { label: params };
} }
//params.deleteOnClose ||= true; //params.deleteOnClose ||= true;
params.buttonsPosition ||= 'bottom';
const modal = document.createElement('dialog'); const modal = document.createElement('dialog');
const label = (params.label || params.text); const label = (params.label || params.text);
let buttonCancel = `<button name="cancel">${params.cancelText || '🔙️ Cancel'}</button>`;
let buttonConfirm = '';
if (params.actionConfirm || params.action) {
buttonConfirm = `<button name="confirm">${params.confirmText || '⏩️ Confirm'}</button>`;
}
modal.innerHTML = ` modal.innerHTML = `
${label ? `<p>${label}</p>` : ''} ${label ? `<p>${label}</p>` : ''}
${params.extraHTML || ''}
<button name="cancel">🔙 Cancel</button>
`; `;
const buttonsHtml = `<p>
${buttonCancel}
${buttonConfirm}
</p>`;
if (params.buttonsPosition == 'top') {
modal.innerHTML += `${buttonsHtml}`;
}
modal.innerHTML += `${params.extraHTML || ''}`;
if (params.buttonsPosition == 'bottom') {
modal.innerHTML += `${buttonsHtml}`;
}
if (params.actionConfirm || params.action) { if (params.actionConfirm || params.action) {
modal.innerHTML += ` buttonConfirm = modal.querySelector('button[name="confirm"]');
<button name="confirm"> Confirm</button>
`;
const buttonConfirm = modal.querySelector('button[name="confirm"]');
buttonConfirm.onclick = (event) => { buttonConfirm.onclick = (event) => {
output = (params.actionConfirm || params.action)(event, buttonConfirm); output = (params.actionConfirm || params.action)(event, buttonConfirm);
modal.close(); modal.close();
return output; return output;
}; };
} }
const buttonCancel = modal.querySelector('button[name="cancel"]'); buttonCancel = modal.querySelector('button[name="cancel"]');
buttonCancel.onclick = (event) => { buttonCancel.onclick = (event) => {
if (params.actionCancel) { if (params.actionCancel) {
output = actionCancel(event, buttonCancel); output = actionCancel(event, buttonCancel);
@ -65,7 +82,9 @@
} }
modal.showModal(); modal.showModal();
return modal; return modal;
} };
SpaccDotWeb.Sleep = (ms) => (new Promise((resolve) => setTimeout(resolve, ms)));
window.SpaccDotWeb ||= SpaccDotWeb; window.SpaccDotWeb ||= SpaccDotWeb;
})(); })();

57
SpaccDotWeb.Build.js Normal file → Executable file
View File

@ -1,31 +1,52 @@
#!/usr/bin/env node
const Lib = { const Lib = {
fs: require('fs'), fs: require('fs'),
mime: require('mime-types'),
crypto: require('crypto'), crypto: require('crypto'),
childProcess: require('child_process'), babel: require('@babel/core'),
jsdom: require('jsdom'), uglify: require('uglify-js'),
}; };
const BuildScriptFile = (scriptFile) => { const BuildScriptFile = (scriptFile, options) => {
options = {
forceResult: false,
checkHash: true,
...options };
Lib.fs.mkdirSync(`${__dirname}/Build`, { recursive: true }); Lib.fs.mkdirSync(`${__dirname}/Build`, { recursive: true });
//let uptodate = true;
const __scriptname = scriptFile.split('/').slice(-1)[0].split('.').slice(0, -1).join('.'); const __scriptname = scriptFile.split('/').slice(-1)[0].split('.').slice(0, -1).join('.');
const scriptScript = Lib.fs.readFileSync(scriptFile, 'utf8');
const compiledPath = `${__dirname}/Build/${__scriptname}.js`; const compiledPath = `${__dirname}/Build/${__scriptname}.js`;
const minifiedPath = `${__dirname}/Build/${__scriptname}.min.js`; const minifiedPath = `${__dirname}/Build/${__scriptname}.min.js`;
const hashPath = `${__dirname}/Build/${__scriptname}.js.hash`; const hashPath = `${__dirname}/Build/${__scriptname}.js.hash`;
const hashOld = (Lib.fs.existsSync(hashPath) && Lib.fs.readFileSync(hashPath, 'utf8')); const hashOld = (Lib.fs.existsSync(hashPath) && Lib.fs.readFileSync(hashPath, 'utf8'));
const hashNew = Lib.crypto.createHash('sha256').update(Lib.fs.readFileSync(scriptFile, 'utf8')).digest('hex'); const hashNew = Lib.crypto.createHash('sha256').update(scriptScript).digest('hex');
if (!Lib.fs.existsSync(compiledPath) || !Lib.fs.existsSync(minifiedPath) || !(hashOld === hashNew)) { if (!options.checkHash || !Lib.fs.existsSync(compiledPath) || !Lib.fs.existsSync(minifiedPath) || !(hashOld === hashNew)) {
//uptodate = false; const compiledScript = Lib.babel.transformSync(scriptScript,
JSON.parse(Lib.fs.readFileSync(`${__dirname}/babel.config.json`, 'utf8'))).code;
const minifiedScript = Lib.uglify.minify(compiledScript).code;
Lib.fs.writeFileSync(compiledPath, compiledScript);
Lib.fs.writeFileSync(minifiedPath, minifiedScript);
Lib.fs.writeFileSync(hashPath, hashNew); Lib.fs.writeFileSync(hashPath, hashNew);
Lib.fs.writeFileSync(compiledPath, Lib.childProcess.execSync(`cat "${scriptFile}" | npx babel -f "${__scriptname}.js"`)); return { compiled: compiledScript, minified: minifiedScript };
Lib.fs.writeFileSync(minifiedPath, Lib.childProcess.execSync(`cat "${compiledPath}" | npx uglifyjs`)); }
}; return { notice: `Target "${scriptFile}" is up-to-date.`, ...(options.forceResult && {
//uptodate && console.log('Target is up-to-date.'); compiled: Lib.fs.readFileSync(compiledPath, 'utf8'),
//return { compiledText: Lib.fs.readFileSync(compiledPath, 'utf8'), minified: Lib.fs.readFileSync(minifiedPath, 'utf8') }; minified: Lib.fs.readFileSync(minifiedPath, 'utf8'),
}) };
};
//const BuildHtmlFile = (htmlFile) => {
//
//}
const EncodeStaticFiles = (files, /* encoding='base64' */) => {
const data = {};
files.forEach(file => (data[file] = `data:${Lib.mime.lookup(file)};base64,${Lib.fs.readFileSync(file).toString('base64')}`));
return data;
};
module.exports = { BuildScriptFile, EncodeStaticFiles };
if (require.main === module) {
console.log(eval(process.argv.slice(-1)[0]));
} }
const BuildHtmlFile = (htmlFile) => {
}
console.log(eval(process.argv.slice(-1)[0]));

23
SpaccDotWeb.js Normal file → Executable file
View File

@ -1,3 +1,4 @@
#!/usr/bin/env node
const SpaccDotWeb = ((args) => { ////////////////////////////////////////////// const SpaccDotWeb = ((args) => { //////////////////////////////////////////////
@ -16,6 +17,7 @@ if (platformIsNode) {
Lib.crypto = require('crypto'); Lib.crypto = require('crypto');
Lib.childProcess = require('child_process'); Lib.childProcess = require('child_process');
Lib.jsdom = require('jsdom'); Lib.jsdom = require('jsdom');
Lib.Build = require('./SpaccDotWeb.Build.js').BuildScriptFile;
__scriptname = __filename__.split('/').slice(-1)[0]; __scriptname = __filename__.split('/').slice(-1)[0];
windowObject = new Lib.jsdom.JSDOM('', JsdomOptions).window; windowObject = new Lib.jsdom.JSDOM('', JsdomOptions).window;
}; };
@ -50,24 +52,6 @@ if (platformIsNode) {
isBuildingApp = false; isBuildingApp = false;
}; };
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') };
};
}; };
SpaccDotWeb.AppInit = () => { SpaccDotWeb.AppInit = () => {
@ -128,7 +112,7 @@ const DomMakeBase = (Modules) => {
if (isBuildingApp) { if (isBuildingApp) {
scriptsHtml += `<scr`+`ipt src="http://cdn.jsdelivr.net/npm/core-js-bundle/minified.min.js"></scr`+`ipt>`; scriptsHtml += `<scr`+`ipt src="http://cdn.jsdelivr.net/npm/core-js-bundle/minified.min.js"></scr`+`ipt>`;
scriptsHtml += `<scr`+`ipt src="https://cdn.jsdelivr.net/npm/core-js-bundle/minified.min.js"></scr`+`ipt>`; scriptsHtml += `<scr`+`ipt src="https://cdn.jsdelivr.net/npm/core-js-bundle/minified.min.js"></scr`+`ipt>`;
scriptsHtml += `<scr`+`ipt>${SpaccDotWeb.LibBuild().minified}</scr`+`ipt>`; scriptsHtml += `<scr`+`ipt>${Lib.Build(__filename__, { forceResult: true }).minified}</scr`+`ipt>`;
for (const elem of documentObject.querySelectorAll('script[module]')) { for (const elem of documentObject.querySelectorAll('script[module]')) {
//if (elem.module === 'Meta' && !['application/json', 'text/json'].includes(elem.type)) { //if (elem.module === 'Meta' && !['application/json', 'text/json'].includes(elem.type)) {
// elem.innerHTML = `(${elem.innerHTML})`; // elem.innerHTML = `(${elem.innerHTML})`;
@ -140,6 +124,7 @@ const DomMakeBase = (Modules) => {
} else { } else {
const tmpHash = Lib.crypto.createHash('sha256').update(elem.innerHTML).digest('hex'); const tmpHash = Lib.crypto.createHash('sha256').update(elem.innerHTML).digest('hex');
const tmpPath = `${__dirname}/Build/Assets.tmp/${tmpHash}.js`; const tmpPath = `${__dirname}/Build/Assets.tmp/${tmpHash}.js`;
Lib.fs.mkdirSync(`${__dirname}/Build/Assets.tmp`, { recursive: true });
Lib.fs.writeFileSync(tmpPath, elem.innerHTML); Lib.fs.writeFileSync(tmpPath, elem.innerHTML);
const scriptCode = Lib.childProcess.execSync(`cat "${tmpPath}" | npx babel -f "${tmpHash}.js" | npx uglifyjs`); const scriptCode = Lib.childProcess.execSync(`cat "${tmpPath}" | npx babel -f "${tmpHash}.js" | npx uglifyjs`);
scriptsCode += scriptCode; scriptsCode += scriptCode;

1293
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@
"build:clear": "rm -rf ./Build" "build:clear": "rm -rf ./Build"
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.23.0", "@babel/cli": "^7.24.8",
"@babel/core": "^7.23.0", "@babel/core": "^7.23.0",
"@babel/preset-env": "^7.22.20", "@babel/preset-env": "^7.22.20",
"core-js": "^3.35.0", "core-js": "^3.35.0",

28
patched-requests.js Normal file
View File

@ -0,0 +1,28 @@
(function(){
if (window.URL) {
var _URL = window.URL;
window.URL = (function URL (url, base) {
try {
return new (Function.prototype.bind.apply(_URL, [{}].concat([url, base])));
} catch (err) {
url = (
window.SpaccDotWebServer.staticFilesData[url] ||
window.SpaccDotWebServer.staticFilesData[`./${url}`] ||
url);
return { href: url, toString: (function(){ return url; }) };
}
});
}
if (window.fetch) {
var _fetch = window.fetch;
window.fetch = (function fetch (resource, options) {
return _fetch((
window.SpaccDotWebServer.staticFilesData[resource] ||
window.SpaccDotWebServer.staticFilesData[`./${resource}`] ||
resource), options);
});
}
})();