[Alt] Fix errors, add element creation to $(); [Build] Updates and example

This commit is contained in:
2025-03-12 00:50:58 +01:00
parent 21fb956b46
commit 8b47ef18b0
8 changed files with 1269 additions and 304 deletions

View File

@ -2,7 +2,7 @@
. ./BuildLib.sh
buildHtml(){
useBuilder "Build.BuildHtmlFile('$1', { outputFile: '$2' })"
useBuilder "BuildHtmlFile('$1', { outputFile: '$2' })"
}
for example in Server

View File

@ -5,7 +5,7 @@ useBuilder(){
}
buildScript(){
useBuilder "Build.BuildScriptFile('$1')"
useBuilder "BuildScriptFile('$1')"
}
for file in ./SpaccDotWeb.js ./SpaccDotWeb.*.js

View File

@ -92,23 +92,27 @@
SpaccDotWeb.sleep = (ms) => (new Promise((resolve) => setTimeout(resolve, ms)));
SpaccDotWeb.Sleep = SpaccDotWeb.sleep;
SpaccDotWeb.$ = (query) => {
SpaccDotWeb.$ = (query, extra) => ((query.startsWith('<') && query.endsWith('>'))
? Object.assign(Object.assign(document.createElement('div'), { innerHTML: query }).querySelector('*'), extra)
: SpaccDotWeb.query(query));
SpaccDotWeb.query = (query) => {
query = query.trim();
return (query.startsWith('::')
? arrayFrom(document.querySelectorAll(domSpecialQuery(query.slice(2).trim())))
? Array.from(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) {
for (const char of `${query} `) {
if (brackets === 0) {
if (buffer.length > 0) {
buffer = buffer.join('');
if (!buffer.includes('=')) {
if (!buffer.includes('=') && (buffer.includes('"') || buffer.includes("'"))) {
buffer = `name=${buffer}`;
}
chars.push(buffer);

View File

@ -31,32 +31,31 @@ alerter("It's a nice day today, innit?");
</fieldset>
<script>
const BuildScript = window.SpaccDotWeb.Build.BuildScript;
const Build = window.SpaccDotWeb.Build;
const $ = (id) => document.getElementById(id);
const createElement = (tag, attrs) => Object.assign(document.createElement(tag), attrs);
// Get the sample script
const scriptText = $('script').textContent = $('script').textContent.trimEnd();
// Actually build the script
const builtScript = BuildScript(scriptText);
const builtScript = Build.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;
Build.BuildHtml(document.documentElement.outerHTML, {}).then(html => {
$('html').textContent = html;
document.querySelector('fieldset.html > span').innerHTML += `, ${html.length}b`;
});
$('html').textContent = `<!DOCTYPE html>\n${document.documentElement.outerHTML}`;
}, 100);
}, 1);
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'), {
fieldset.appendChild(createElement('button', {
innerHTML: "Execute",
onclick: () => eval(script),
}));

View File

@ -34,35 +34,49 @@ const babelConfig = {
],
};
const findPath = (path, folder) => {
for (const prefix of [folder, __dirname]) {
path = Lib.path.join(prefix, path);
if (Lib.fs.existsSync(path)) {
const findPath = (path, folder, files) => {
for (const prefix of [folder, (typeof __dirname !== 'undefined' ? __dirname : '')]) {
path = (Lib.path?.join(prefix, path) || `${prefix}/${path}`);
if ((files && (path in files)) || (!files && Lib.fs?.existsSync(path))) {
return path;
}
}
};
const readFile = (path, folder, files) => {
path = (findPath(path, folder, files) || path);
return (files ? files[path] : Lib.fs?.readFileSync(path, 'utf8'));
}
const fileToBase64 = (path, content) => `data:${Lib.mime.lookup(path)};base64,${content || Lib.fs.readFileSync(findPath(path)).toString('base64')}`;
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 };
options ||= {};
options.minify ??= true;
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 BuildStyle = async (styleText, stylePath, options) => {
options ||= {};
options.minify ??= true;
const plugins = [
Lib.postcssImport(),
Lib.postcssUrl({ url: 'inline' }),
...(options.minify ? [Lib.postcssMinify()] : []),
];
return (await Lib.postcss(plugins).process(styleText, { from: stylePath })).css;
};
const BuildHtml = async (html, options, files) => {
options ||= {};
options.compileScripts ??= true;
options.minifyScripts ??= true;
options.compileStyles ??= true;
options.inputFolder ??= '.';
const dom = makeHtmlDom(html);
for (const element of dom.querySelectorAll('script, [src], link[rel=stylesheet][href]')) {
if (isUrlAbsolute(element.src || element.href)) {
@ -72,21 +86,20 @@ const BuildHtml = async (html, options) => {
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')
? readFile(element.src, options.inputFolder, files) //Lib.fs.readFileSync(findPath(element.src, options.inputFolder), 'utf8')
: element.textContent);
if (scriptOptions.compile ?? options.compileScripts) {
scriptText = BuildScript(scriptText, { minify: minifyScripts })[minifyScripts ? 'minified' : 'compiled'];
}
if (scriptText) {
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;
let styleText = readFile(stylePath, options.inputFolder, files); //Lib.fs.readFileSync(stylePath, 'utf8');
if (options.compileStyles && !envIsBrowser) {
styleText = await BuildStyle(styleText, stylePath, { minify: options.minifyStyles });
}
element.parentElement.insertBefore(Object.assign(dom.createElement('style'), { textContent: styleText }), element);
element.remove();
@ -95,7 +108,7 @@ const BuildHtml = async (html, options) => {
}
}
return `<!DOCTYPE html>\n${dom.documentElement.outerHTML}`;
}
};
return { BuildScript, BuildHtml, fileToBase64 };

View File

@ -7,6 +7,7 @@ const Lib = {
babel: require('@babel/core'),
uglify: require('uglify-js'),
postcss: require('postcss'),
postcssMinify: require('postcss-minify'),
postcssImport: require('postcss-import'),
postcssUrl: require('postcss-url'),
jsdom: require('jsdom').JSDOM,
@ -41,11 +42,10 @@ const BuildScriptFile = (scriptFile, options) => {
};
const BuildHtmlFile = (htmlFile, options) => {
options = {
outputFolder: './Build',
outputFile: htmlFile,
inputFolder: Lib.path.dirname(htmlFile),
...options };
options ||= {};
options.outputFile ??= htmlFile;
options.inputFolder ??= Lib.path.dirname(htmlFile);
options.outputFolder ??= './Build';
const outputPath = `${options.outputFolder}/${options.outputFile}`;
Build.BuildHtml(Lib.fs.readFileSync(htmlFile, 'utf8'), options).then(html => Lib.fs.writeFileSync(outputPath, html));
return outputPath;
@ -60,5 +60,5 @@ const EncodeStaticFiles = (files, /* encoding='base64' */) => {
module.exports = Build = { ...Build, BuildScriptFile, BuildHtmlFile, EncodeStaticFiles };
if (require.main === module) {
console.log(eval(process.argv.slice(-1)[0]));
console.log(eval('Build.'+process.argv.slice(-1)[0]));
}

1444
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -17,13 +17,24 @@
"jsdom": "^22.1.0",
"postcss": "^8.5.3",
"postcss-import": "^16.1.0",
"postcss-minify": "^1.1.0",
"postcss-url": "^10.1.3",
"uglify-js": "^3.17.4",
"uglifyjs-browser": "^3.0.0"
},
"dependencies": {
"buffer": "^6.0.3",
"crypto-browserify": "^3.12.1",
"events": "^3.3.0",
"fs-web": "^1.0.1",
"mime-types": "^2.1.35",
"mime-types-browser": "^0.0.3",
"parse-multipart-data": "^1.5.0"
"os-browserify": "^0.3.0",
"parse-multipart-data": "^1.5.0",
"path-browserify": "^1.0.1",
"process": "^0.11.10",
"stream-browserify": "^3.0.0",
"url": "^0.11.4",
"util": "^0.12.5"
}
}