mirror of
https://gitlab.com/SpaccInc/SpaccDotWeb.git
synced 2025-06-05 21:29:12 +02:00
[Alt] Add new methods; [Server] Slight improvements to example; [Build] Add full HTML build
This commit is contained in:
parent
5338c8aaf6
commit
fedb597dda
18
BuildExamples.sh
Normal file
18
BuildExamples.sh
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. ./BuildLib.sh
|
||||||
|
|
||||||
|
buildHtml(){
|
||||||
|
useBuilder "Build.BuildHtmlFile('$1', { outputFile: '$2' })"
|
||||||
|
}
|
||||||
|
|
||||||
|
for example in Server
|
||||||
|
do
|
||||||
|
example="Example.${example}"
|
||||||
|
file="./${example}/index.js"
|
||||||
|
node "${file}" writeStaticHtml 0 "./${example}/index.html"
|
||||||
|
node "${file}" writeStaticHtml 1 "./Build/${example}.html"
|
||||||
|
done
|
||||||
|
|
||||||
|
for example in Build
|
||||||
|
do buildHtml "./SpaccDotWeb.${example}/Example.html" "SpaccDotWeb.${example}.Example.html"
|
||||||
|
done
|
19
BuildLib.sh
Executable file → Normal file
19
BuildLib.sh
Executable file → Normal file
@ -1,4 +1,21 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
useBuilder(){
|
||||||
|
node ./SpaccDotWeb.Build/node.js "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildScript(){
|
||||||
|
useBuilder "Build.BuildScriptFile('$1')"
|
||||||
|
}
|
||||||
|
|
||||||
for file in ./SpaccDotWeb.js ./SpaccDotWeb.*.js
|
for file in ./SpaccDotWeb.js ./SpaccDotWeb.*.js
|
||||||
do node ./SpaccDotWeb.Build.js "BuildScriptFile('${file}')"
|
do buildScript "${file}"
|
||||||
|
done
|
||||||
|
|
||||||
|
for lib in Build
|
||||||
|
do
|
||||||
|
lib="SpaccDotWeb.${lib}"
|
||||||
|
output="./Build/${lib}.bundle.min.js"
|
||||||
|
npx esbuild "./${lib}/browser.js" --bundle --minify --outfile="${output}"
|
||||||
|
#buildScript "${output}"
|
||||||
done
|
done
|
||||||
|
@ -21,3 +21,17 @@ div#transition {
|
|||||||
cursor: progress;
|
cursor: progress;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.particles {
|
||||||
|
position: absolute;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.particles > * {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
5
Example.Server/index.js
Executable file → Normal file
5
Example.Server/index.js
Executable file → Normal file
@ -14,7 +14,10 @@ const server = SpaccDotWebServer.setup({
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (SpaccDotWebServer.envIsNode && ['dump', 'html', 'writeStaticHtml'].includes(process.argv[2])) {
|
if (SpaccDotWebServer.envIsNode && ['dump', 'html', 'writeStaticHtml'].includes(process.argv[2])) {
|
||||||
const fileName = server.writeStaticHtml(Number(process.argv[3] || 0));
|
const fileName = server.writeStaticHtml({
|
||||||
|
selfContained: Number(process.argv[3] || 0),
|
||||||
|
htmlFilePath: process.argv[4],
|
||||||
|
});
|
||||||
console.log(`Dumped Static HTML to '${fileName}'!`);
|
console.log(`Dumped Static HTML to '${fileName}'!`);
|
||||||
} else {
|
} else {
|
||||||
const serverData = server.initServer({
|
const serverData = server.initServer({
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
window.addEventListener('load', function(){
|
window.addEventListener('load', function(){
|
||||||
|
var c = Object.assign(document.createElement('div'), { className: "particles" });
|
||||||
|
document.body.appendChild(c);
|
||||||
for (var i=0; i<(window.innerWidth * window.innerHeight / 6000); i++) (function(){
|
for (var i=0; i<(window.innerWidth * window.innerHeight / 6000); i++) (function(){
|
||||||
var v = (Math.random() * window.innerHeight), h = (100 * Math.random());
|
var v = (Math.random() * window.innerHeight), h = (100 * Math.random());
|
||||||
var n = document.createElement('span');
|
var n = document.createElement('span');
|
||||||
n.textContent = '✨️';
|
n.textContent = '✨️';
|
||||||
n.style.position = 'absolute';
|
c.appendChild(n);
|
||||||
document.body.appendChild(n);
|
|
||||||
var e = setInterval(function(){
|
var e = setInterval(function(){
|
||||||
var r = Math.random();
|
var r = Math.random();
|
||||||
n.style.top = (v += 1).toString() + 'px';
|
n.style.top = (v += 1).toString() + 'px';
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
document.body.appendChild(scriptElem);
|
document.body.appendChild(scriptElem);
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
// .RequireScripts = (...) => {}
|
|
||||||
SpaccDotWeb.RequireScript = SpaccDotWeb.requireScript;
|
SpaccDotWeb.RequireScript = SpaccDotWeb.requireScript;
|
||||||
|
|
||||||
SpaccDotWeb.showModal = async (params) => {
|
SpaccDotWeb.showModal = async (params) => {
|
||||||
@ -76,7 +75,7 @@
|
|||||||
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 = params.actionCancel(event, buttonCancel);
|
||||||
}
|
}
|
||||||
modal.close();
|
modal.close();
|
||||||
return output;
|
return output;
|
||||||
@ -93,5 +92,40 @@
|
|||||||
SpaccDotWeb.sleep = (ms) => (new Promise((resolve) => setTimeout(resolve, ms)));
|
SpaccDotWeb.sleep = (ms) => (new Promise((resolve) => setTimeout(resolve, ms)));
|
||||||
SpaccDotWeb.Sleep = SpaccDotWeb.sleep;
|
SpaccDotWeb.Sleep = SpaccDotWeb.sleep;
|
||||||
|
|
||||||
|
SpaccDotWeb.$ = (query) => {
|
||||||
|
query = query.trim();
|
||||||
|
return (query.startsWith('::')
|
||||||
|
? arrayFrom(document.querySelectorAll(domSpecialQuery(query.slice(2).trim())))
|
||||||
|
: document.querySelector(domSpecialQuery(query))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function domSpecialQuery (query) {
|
||||||
|
const chars = [];
|
||||||
|
let buffer = [];
|
||||||
|
let brackets = 0;
|
||||||
|
for (const char of query) {
|
||||||
|
if (brackets === 0) {
|
||||||
|
if (buffer.length > 0) {
|
||||||
|
buffer = buffer.join('');
|
||||||
|
if (!buffer.includes('=')) {
|
||||||
|
buffer = `name=${buffer}`;
|
||||||
|
}
|
||||||
|
chars.push(buffer);
|
||||||
|
buffer = [];
|
||||||
|
}
|
||||||
|
chars.push(char);
|
||||||
|
} else {
|
||||||
|
buffer.push(char);
|
||||||
|
}
|
||||||
|
if (char === '[') {
|
||||||
|
brackets++;
|
||||||
|
} else if (char === ']' && brackets > 0) {
|
||||||
|
brackets--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return chars.join('');
|
||||||
|
}
|
||||||
|
|
||||||
window.SpaccDotWeb ||= SpaccDotWeb;
|
window.SpaccDotWeb ||= SpaccDotWeb;
|
||||||
})(document.currentScript);
|
})(document.currentScript);
|
||||||
|
0
SpaccDotWeb.Android/gradlew
vendored
Executable file → Normal file
0
SpaccDotWeb.Android/gradlew
vendored
Executable file → Normal file
@ -1,52 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
const Lib = {
|
|
||||||
fs: require('fs'),
|
|
||||||
mime: require('mime-types'),
|
|
||||||
crypto: require('crypto'),
|
|
||||||
babel: require('@babel/core'),
|
|
||||||
uglify: require('uglify-js'),
|
|
||||||
};
|
|
||||||
|
|
||||||
const BuildScriptFile = (scriptFile, options) => {
|
|
||||||
options = {
|
|
||||||
forceResult: false,
|
|
||||||
checkHash: true,
|
|
||||||
...options };
|
|
||||||
Lib.fs.mkdirSync(`${__dirname}/Build`, { recursive: true });
|
|
||||||
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 minifiedPath = `${__dirname}/Build/${__scriptname}.min.js`;
|
|
||||||
const hashPath = `${__dirname}/Build/${__scriptname}.js.hash`;
|
|
||||||
const hashOld = (Lib.fs.existsSync(hashPath) && Lib.fs.readFileSync(hashPath, 'utf8'));
|
|
||||||
const hashNew = Lib.crypto.createHash('sha256').update(scriptScript).digest('hex');
|
|
||||||
if (!options.checkHash || !Lib.fs.existsSync(compiledPath) || !Lib.fs.existsSync(minifiedPath) || !(hashOld === hashNew)) {
|
|
||||||
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);
|
|
||||||
return { compiled: compiledScript, minified: minifiedScript };
|
|
||||||
}
|
|
||||||
return { notice: `Target "${scriptFile}" is up-to-date.`, ...(options.forceResult && {
|
|
||||||
compiled: Lib.fs.readFileSync(compiledPath, '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]));
|
|
||||||
}
|
|
64
SpaccDotWeb.Build/Example.html
Normal file
64
SpaccDotWeb.Build/Example.html
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf8" />
|
||||||
|
<style> textarea { width: 100% !important; height: 8rem; min-height: 2em; box-sizing: border-box; } </style>
|
||||||
|
<script src="../Build/SpaccDotWeb.Build.bundle.min.js" data-SpaccDotWeb='{"compile":false,"minify":false}'></script>
|
||||||
|
|
||||||
|
<fieldset class="script">
|
||||||
|
<legend>Script</legend>
|
||||||
|
<textarea id="script" readonly="true">
|
||||||
|
const alerter = (text) => alert(`THIS IS AN ALERT ❗️\n\n${text}`);
|
||||||
|
alerter("It's a nice day today, innit?");
|
||||||
|
</textarea>
|
||||||
|
<span>ES6</span>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset class="script">
|
||||||
|
<legend>Compiled</legend>
|
||||||
|
<textarea id="compiled" readonly="true"></textarea>
|
||||||
|
<span>ES5</span>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset class="script">
|
||||||
|
<legend>Compiled+Minified</legend>
|
||||||
|
<textarea id="minified" readonly="true"></textarea>
|
||||||
|
<span>ES5</span>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset class="html">
|
||||||
|
<legend>HTML</legend>
|
||||||
|
<textarea id="html" readonly="true"></textarea>
|
||||||
|
<span>ES5, Compiled+Minified</span>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const BuildScript = window.SpaccDotWeb.Build.BuildScript;
|
||||||
|
const $ = (id) => document.getElementById(id);
|
||||||
|
|
||||||
|
const scriptText = $('script').textContent = $('script').textContent.trimEnd();
|
||||||
|
|
||||||
|
// Actually build the script
|
||||||
|
const builtScript = BuildScript(scriptText);
|
||||||
|
|
||||||
|
// Show the build result
|
||||||
|
$('compiled').textContent = builtScript.compiled;
|
||||||
|
$('minified').textContent = builtScript.minified;
|
||||||
|
|
||||||
|
// Execute the compiled result
|
||||||
|
//setTimeout('eval(builtScript.compiled);', 100);
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
Array.from(document.querySelectorAll('script')).filter(el => !el.dataset.spaccdotweb).forEach(scriptElement => {
|
||||||
|
scriptElement.textContent = BuildScript(scriptElement.textContent).minified;
|
||||||
|
});
|
||||||
|
$('html').textContent = `<!DOCTYPE html>\n${document.documentElement.outerHTML}`;
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
document.querySelectorAll('fieldset.script').forEach(fieldset => {
|
||||||
|
const script = fieldset.querySelector('textarea').textContent;
|
||||||
|
fieldset.querySelector('span').innerHTML += `, ${script.length}b`;
|
||||||
|
fieldset.appendChild(Object.assign(document.createElement('button'), {
|
||||||
|
innerHTML: "Execute",
|
||||||
|
onclick: () => eval(script),
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
</script>
|
7
SpaccDotWeb.Build/browser.js
Normal file
7
SpaccDotWeb.Build/browser.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
window.global ||= window.globalThis;
|
||||||
|
window.SpaccDotWeb ||= {};
|
||||||
|
window.SpaccDotWeb.Build = require('./lib.js')({
|
||||||
|
mime: require('mime-types-browser/dist/mime-types-browser'),
|
||||||
|
babel: require('@babel/standalone'),
|
||||||
|
uglify: require('uglifyjs-browser'),
|
||||||
|
});
|
102
SpaccDotWeb.Build/lib.js
Normal file
102
SpaccDotWeb.Build/lib.js
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
module.exports = (Lib) => {
|
||||||
|
|
||||||
|
const envIsBrowser = (typeof window !== 'undefined' && typeof window.document !== 'undefined');
|
||||||
|
|
||||||
|
let babelPreset, makeHtmlDom;
|
||||||
|
|
||||||
|
if (envIsBrowser) {
|
||||||
|
Lib.babel.registerPreset(null, {
|
||||||
|
presets: [
|
||||||
|
[Lib.babel.availablePresets['preset-env']],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
babelPreset = 'env';
|
||||||
|
makeHtmlDom = (html) => (new DOMParser()).parseFromString(html, 'text/html');
|
||||||
|
} else {
|
||||||
|
babelPreset = '@babel/preset-env';
|
||||||
|
makeHtmlDom = (html) => (new Lib.jsdom(html)).window.document;
|
||||||
|
}
|
||||||
|
|
||||||
|
const babelConfig = {
|
||||||
|
"presets": [
|
||||||
|
[
|
||||||
|
babelPreset,
|
||||||
|
{
|
||||||
|
"targets": {
|
||||||
|
"chrome": "4",
|
||||||
|
"edge": "12",
|
||||||
|
"firefox": "2",
|
||||||
|
"ie": "6",
|
||||||
|
"safari": "3.1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const findPath = (path, folder) => {
|
||||||
|
for (const prefix of [folder, __dirname]) {
|
||||||
|
path = Lib.path.join(prefix, path);
|
||||||
|
if (Lib.fs.existsSync(path)) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileToBase64 = (path, content) => `data:${Lib.mime.lookup(path)};base64,${content || Lib.fs.readFileSync(findPath(path)).toString('base64')}`;
|
||||||
|
|
||||||
|
const isUrlAbsolute = (url) => (url && ['http:', 'https:', ''].includes(url.split('/')[0]));
|
||||||
|
|
||||||
|
const BuildScript = (scriptText, options) => {
|
||||||
|
options = {
|
||||||
|
minify: true,
|
||||||
|
...options };
|
||||||
|
const compiled = (Lib.babel.transformSync || Lib.babel.transform)(scriptText, babelConfig).code;
|
||||||
|
const minified = (options.minify && Lib.uglify.minify(compiled).code);
|
||||||
|
return { compiled, minified };
|
||||||
|
}
|
||||||
|
|
||||||
|
const BuildHtml = async (html, options) => {
|
||||||
|
options = {
|
||||||
|
compileScripts: true,
|
||||||
|
minifyScripts: true,
|
||||||
|
compileStyles: true,
|
||||||
|
inputFolder: '.',
|
||||||
|
...options };
|
||||||
|
const dom = makeHtmlDom(html);
|
||||||
|
for (const element of dom.querySelectorAll('script, [src], link[rel=stylesheet][href]')) {
|
||||||
|
if (isUrlAbsolute(element.src || element.href)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (element.tagName === 'SCRIPT') {
|
||||||
|
const scriptOptions = JSON.parse(element.dataset.spaccdotweb || '{}');
|
||||||
|
const minifyScripts = (scriptOptions.minify ?? options.minifyScripts);
|
||||||
|
let scriptText = (element.src
|
||||||
|
? Lib.fs.readFileSync(findPath(element.src, options.inputFolder), 'utf8')
|
||||||
|
: element.textContent);
|
||||||
|
if (scriptOptions.compile ?? options.compileScripts) {
|
||||||
|
scriptText = BuildScript(scriptText, { minify: minifyScripts })[minifyScripts ? 'minified' : 'compiled'];
|
||||||
|
}
|
||||||
|
element.removeAttribute('src');
|
||||||
|
element.textContent = scriptText;
|
||||||
|
} else if (element.tagName === 'LINK') {
|
||||||
|
const stylePath = findPath(element.href, options.inputFolder);
|
||||||
|
let styleText = Lib.fs.readFileSync(stylePath, 'utf8');
|
||||||
|
if (options.compileStyles) {
|
||||||
|
styleText = (await Lib.postcss([
|
||||||
|
Lib.postcssImport(),
|
||||||
|
Lib.postcssUrl({ url: 'inline' }),
|
||||||
|
]).process(styleText, { from: stylePath })).css;
|
||||||
|
}
|
||||||
|
element.parentElement.insertBefore(Object.assign(dom.createElement('style'), { textContent: styleText }), element);
|
||||||
|
element.remove();
|
||||||
|
} else {
|
||||||
|
element.src = fileToBase64(element.src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `<!DOCTYPE html>\n${dom.documentElement.outerHTML}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { BuildScript, BuildHtml, fileToBase64 };
|
||||||
|
|
||||||
|
}
|
64
SpaccDotWeb.Build/node.js
Normal file
64
SpaccDotWeb.Build/node.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
const Lib = {
|
||||||
|
fs: require('fs'),
|
||||||
|
path: require('path'),
|
||||||
|
mime: require('mime-types'),
|
||||||
|
crypto: require('crypto'),
|
||||||
|
babel: require('@babel/core'),
|
||||||
|
uglify: require('uglify-js'),
|
||||||
|
postcss: require('postcss'),
|
||||||
|
postcssImport: require('postcss-import'),
|
||||||
|
postcssUrl: require('postcss-url'),
|
||||||
|
jsdom: require('jsdom').JSDOM,
|
||||||
|
};
|
||||||
|
let Build = require('./lib.js')(Lib);
|
||||||
|
|
||||||
|
const BuildScriptFile = (scriptFile, options) => {
|
||||||
|
options = {
|
||||||
|
forceResult: false,
|
||||||
|
checkHash: true,
|
||||||
|
outputFolder: './Build',
|
||||||
|
...options };
|
||||||
|
Lib.fs.mkdirSync(options.outputFolder, { recursive: true });
|
||||||
|
const __scriptname = scriptFile.split('/').slice(-1)[0].split('.').slice(0, -1).join('.');
|
||||||
|
const scriptText = Lib.fs.readFileSync(scriptFile, 'utf8');
|
||||||
|
const compiledPath = `${options.outputFolder}/${__scriptname}.js`;
|
||||||
|
const minifiedPath = `${options.outputFolder}/${__scriptname}.min.js`;
|
||||||
|
const hashPath = `${options.outputFolder}/${__scriptname}.js.hash`;
|
||||||
|
const hashOld = (Lib.fs.existsSync(hashPath) && Lib.fs.readFileSync(hashPath, 'utf8'));
|
||||||
|
const hashNew = Lib.crypto.createHash('sha256').update(scriptText).digest('hex');
|
||||||
|
if (!options.checkHash || !Lib.fs.existsSync(compiledPath) || !Lib.fs.existsSync(minifiedPath) || !(hashOld === hashNew)) {
|
||||||
|
const builtScript = Build.BuildScript(scriptText, /* JSON.parse(Lib.fs.readFileSync(`${__dirname}/babel.config.json`, 'utf8')) */);
|
||||||
|
Lib.fs.writeFileSync(compiledPath, builtScript.compiled);
|
||||||
|
Lib.fs.writeFileSync(minifiedPath, builtScript.minified);
|
||||||
|
Lib.fs.writeFileSync(hashPath, hashNew);
|
||||||
|
return builtScript;
|
||||||
|
}
|
||||||
|
return { notice: `Target "${scriptFile}" is up-to-date.`, ...(options.forceResult && {
|
||||||
|
compiled: Lib.fs.readFileSync(compiledPath, 'utf8'),
|
||||||
|
minified: Lib.fs.readFileSync(minifiedPath, 'utf8'),
|
||||||
|
}) };
|
||||||
|
};
|
||||||
|
|
||||||
|
const BuildHtmlFile = (htmlFile, options) => {
|
||||||
|
options = {
|
||||||
|
outputFolder: './Build',
|
||||||
|
outputFile: htmlFile,
|
||||||
|
inputFolder: Lib.path.dirname(htmlFile),
|
||||||
|
...options };
|
||||||
|
const outputPath = `${options.outputFolder}/${options.outputFile}`;
|
||||||
|
Build.BuildHtml(Lib.fs.readFileSync(htmlFile, 'utf8'), options).then(html => Lib.fs.writeFileSync(outputPath, html));
|
||||||
|
return outputPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
const EncodeStaticFiles = (files, /* encoding='base64' */) => {
|
||||||
|
const data = {};
|
||||||
|
files.forEach(file => (data[file] = Build.fileToBase64(file)));
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Build = { ...Build, BuildScriptFile, BuildHtmlFile, EncodeStaticFiles };
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
console.log(eval(process.argv.slice(-1)[0]));
|
||||||
|
}
|
@ -82,16 +82,21 @@ const initServer = (serverOptions) => {
|
|||||||
const navigateClientPage = (forceUrl) => ((!forceUrl || (window.location.hash === forceUrl))
|
const navigateClientPage = (forceUrl) => ((!forceUrl || (window.location.hash === forceUrl))
|
||||||
&& handleRequest({ url: window.location.hash.slice(1), method: 'GET' }));
|
&& handleRequest({ url: window.location.hash.slice(1), method: 'GET' }));
|
||||||
|
|
||||||
const writeStaticHtml = (selfContained=false) => {
|
const writeStaticHtml = (options={}) => {
|
||||||
const appFilePath = process.mainModule.filename;
|
const appFilePath = process.mainModule.filename;
|
||||||
const htmlFilePath = (appFilePath.split('.').slice(0, -1).join('.') + '.html');
|
options.selfContained ??= false;
|
||||||
|
options.htmlFilePath ??= (appFilePath.split('.').slice(0, -1).join('.') + '.html');
|
||||||
// path.relative seems to always append an extra '../', so we must slice it
|
// path.relative seems to always append an extra '../', so we must slice it
|
||||||
const libraryPath = path.relative(appFilePath, __filename).split(path.sep).slice(1).join(path.sep);
|
let libraryPath = path.relative(appFilePath, __filename).split(path.sep).slice(1).join(path.sep);
|
||||||
const libraryFolder = libraryPath.split(path.sep).slice(0, -1).join(path.sep);
|
let libraryFolder = libraryPath.split(path.sep).slice(0, -1).join(path.sep);
|
||||||
|
if (path.sep === '\\') {
|
||||||
|
libraryPath = libraryPath.replaceAll('\\', '/');
|
||||||
|
libraryFolder = libraryFolder.replaceAll('\\', '/');
|
||||||
|
}
|
||||||
const context = { envIsNode: false, envIsBrowser: true };
|
const context = { envIsNode: false, envIsBrowser: true };
|
||||||
fs.writeFileSync(htmlFilePath, allOpts.global.htmlPager(`
|
fs.writeFileSync(options.htmlFilePath, allOpts.global.htmlPager(`
|
||||||
${makeHtmlScriptFragment(libraryPath, selfContained)}
|
${makeHtmlScriptFragment(libraryPath, options.selfContained)}
|
||||||
${makeHtmlScriptFragment(((libraryFolder && (libraryFolder + '/')) + 'SpaccDotWeb.Alt.js'), selfContained)}
|
${makeHtmlScriptFragment(((libraryFolder && (libraryFolder + '/')) + 'SpaccDotWeb.Alt.js'), options.selfContained)}
|
||||||
<${'script'}>
|
<${'script'}>
|
||||||
window.require = () => {
|
window.require = () => {
|
||||||
window.require = async (src, type) => {
|
window.require = async (src, type) => {
|
||||||
@ -99,15 +104,15 @@ const writeStaticHtml = (selfContained=false) => {
|
|||||||
};
|
};
|
||||||
return window.SpaccDotWebServer;
|
return window.SpaccDotWebServer;
|
||||||
};
|
};
|
||||||
window.SpaccDotWebServer.staticFilesData = { ${selfContained ? allOpts.global.staticFiles.map((file) => {
|
window.SpaccDotWebServer.staticFilesData = { ${options.selfContained ? allOpts.global.staticFiles.map((file) => {
|
||||||
// TODO check if these paths are correct or must still be fixed
|
// TODO check if these paths are correct or must still be fixed
|
||||||
const filePath = (appFilePath.split(path.sep).slice(0, -1).join(path.sep) + path.sep + file);
|
const filePath = (appFilePath.split(path.sep).slice(0, -1).join(path.sep) + path.sep + file);
|
||||||
return `"${file}":"data:${mime.lookup(filePath)};base64,${fs.readFileSync(filePath).toString('base64')}"`;
|
return `"${file}":"data:${mime.lookup(filePath)};base64,${fs.readFileSync(filePath).toString('base64')}"`;
|
||||||
}).join() : ''} };
|
}).join() : ''} };
|
||||||
</${'script'}>
|
</${'script'}>
|
||||||
${makeHtmlScriptFragment(path.basename(appFilePath), selfContained)}
|
${makeHtmlScriptFragment(path.basename(appFilePath), options.selfContained)}
|
||||||
`, null, { selfContained, context }, context));
|
`, null, { selfContained: options.selfContained, context }, context));
|
||||||
return htmlFilePath;
|
return options.htmlFilePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
const makeHtmlStyleFragment = (path, getContent) => {
|
const makeHtmlStyleFragment = (path, getContent) => {
|
||||||
@ -115,15 +120,18 @@ const makeHtmlStyleFragment = (path, getContent) => {
|
|||||||
return (data[1] ? `<style>${data[1]}</style>` : `<link rel="stylesheet" href="${data[0]}"/>`);
|
return (data[1] ? `<style>${data[1]}</style>` : `<link rel="stylesheet" href="${data[0]}"/>`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const makeHtmlScriptFragment = (path, getContent) => {
|
const makeHtmlScriptFragment = (patha, getContent) => {
|
||||||
const data = getFilePathContent(path, getContent);
|
const data = getFilePathContent(patha, getContent);
|
||||||
return `<${'script'}${data[1] ? `>${data[1]}` : ` src="${data[0]}">`}</${'script'}>`;
|
return `<${'script'}${data[1] ? `>${data[1]}` : ` src="${data[0]}">`}</${'script'}>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFilePathContent = (path, getContent) => ([
|
const getFilePathContent = (filePath, getContent) => {
|
||||||
(allOpts.global.staticFiles.includes(path) ? (allOpts.global.staticPrefix + path) : ('./' + path)),
|
const realPath = path.join(path.dirname(process.mainModule.filename), filePath);
|
||||||
(getContent && fs.existsSync(path) && fs.readFileSync(path)),
|
return [
|
||||||
]);
|
(allOpts.global.staticFiles.includes(filePath) ? (allOpts.global.staticPrefix + filePath) : ('./' + filePath)),
|
||||||
|
(getContent && fs.existsSync(realPath) && fs.readFileSync(realPath)),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
const handleRequest = async (request, response={}) => {
|
const handleRequest = async (request, response={}) => {
|
||||||
// build request context and handle special tasks
|
// build request context and handle special tasks
|
||||||
|
0
SpaccDotWeb.js
Executable file → Normal file
0
SpaccDotWeb.js
Executable file → Normal file
954
package-lock.json
generated
954
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@ -3,19 +3,27 @@
|
|||||||
"version": "indev",
|
"version": "indev",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:lib": "sh ./BuildLib.sh",
|
"build:lib": "sh ./BuildLib.sh",
|
||||||
|
"build:examples": "sh ./BuildExamples.sh",
|
||||||
"build:clear": "rm -rf ./Build"
|
"build:clear": "rm -rf ./Build"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.24.8",
|
"@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",
|
||||||
|
"@babel/standalone": "^7.26.9",
|
||||||
"core-js": "^3.35.0",
|
"core-js": "^3.35.0",
|
||||||
"dialog-polyfill": "^0.5.6",
|
"dialog-polyfill": "^0.5.6",
|
||||||
|
"esbuild": "^0.25.0",
|
||||||
"jsdom": "^22.1.0",
|
"jsdom": "^22.1.0",
|
||||||
"uglify-js": "^3.17.4"
|
"postcss": "^8.5.3",
|
||||||
|
"postcss-import": "^16.1.0",
|
||||||
|
"postcss-url": "^10.1.3",
|
||||||
|
"uglify-js": "^3.17.4",
|
||||||
|
"uglifyjs-browser": "^3.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mime-types": "^2.1.35",
|
"mime-types": "^2.1.35",
|
||||||
|
"mime-types-browser": "^0.0.3",
|
||||||
"parse-multipart-data": "^1.5.0"
|
"parse-multipart-data": "^1.5.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user