mirror of
https://gitlab.com/SpaccInc/SpaccDotWeb.git
synced 2025-06-05 21:29:12 +02:00
[Alt] Fix errors, add element creation to $(); [Build] Updates and example
This commit is contained in:
@ -2,7 +2,7 @@
|
|||||||
. ./BuildLib.sh
|
. ./BuildLib.sh
|
||||||
|
|
||||||
buildHtml(){
|
buildHtml(){
|
||||||
useBuilder "Build.BuildHtmlFile('$1', { outputFile: '$2' })"
|
useBuilder "BuildHtmlFile('$1', { outputFile: '$2' })"
|
||||||
}
|
}
|
||||||
|
|
||||||
for example in Server
|
for example in Server
|
||||||
|
@ -5,7 +5,7 @@ useBuilder(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildScript(){
|
buildScript(){
|
||||||
useBuilder "Build.BuildScriptFile('$1')"
|
useBuilder "BuildScriptFile('$1')"
|
||||||
}
|
}
|
||||||
|
|
||||||
for file in ./SpaccDotWeb.js ./SpaccDotWeb.*.js
|
for file in ./SpaccDotWeb.js ./SpaccDotWeb.*.js
|
||||||
|
@ -92,23 +92,27 @@
|
|||||||
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) => {
|
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();
|
query = query.trim();
|
||||||
return (query.startsWith('::')
|
return (query.startsWith('::')
|
||||||
? arrayFrom(document.querySelectorAll(domSpecialQuery(query.slice(2).trim())))
|
? Array.from(document.querySelectorAll(domSpecialQuery(query.slice(2).trim())))
|
||||||
: document.querySelector(domSpecialQuery(query))
|
: document.querySelector(domSpecialQuery(query))
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
function domSpecialQuery (query) {
|
function domSpecialQuery (query) {
|
||||||
const chars = [];
|
const chars = [];
|
||||||
let buffer = [];
|
let buffer = [];
|
||||||
let brackets = 0;
|
let brackets = 0;
|
||||||
for (const char of query) {
|
for (const char of `${query} `) {
|
||||||
if (brackets === 0) {
|
if (brackets === 0) {
|
||||||
if (buffer.length > 0) {
|
if (buffer.length > 0) {
|
||||||
buffer = buffer.join('');
|
buffer = buffer.join('');
|
||||||
if (!buffer.includes('=')) {
|
if (!buffer.includes('=') && (buffer.includes('"') || buffer.includes("'"))) {
|
||||||
buffer = `name=${buffer}`;
|
buffer = `name=${buffer}`;
|
||||||
}
|
}
|
||||||
chars.push(buffer);
|
chars.push(buffer);
|
||||||
|
@ -31,32 +31,31 @@ alerter("It's a nice day today, innit?");
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const BuildScript = window.SpaccDotWeb.Build.BuildScript;
|
const Build = window.SpaccDotWeb.Build;
|
||||||
const $ = (id) => document.getElementById(id);
|
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();
|
const scriptText = $('script').textContent = $('script').textContent.trimEnd();
|
||||||
|
|
||||||
// Actually build the script
|
// Actually build the script
|
||||||
const builtScript = BuildScript(scriptText);
|
const builtScript = Build.BuildScript(scriptText);
|
||||||
|
|
||||||
// Show the build result
|
// Show the build result
|
||||||
$('compiled').textContent = builtScript.compiled;
|
$('compiled').textContent = builtScript.compiled;
|
||||||
$('minified').textContent = builtScript.minified;
|
$('minified').textContent = builtScript.minified;
|
||||||
|
|
||||||
// Execute the compiled result
|
|
||||||
//setTimeout('eval(builtScript.compiled);', 100);
|
|
||||||
|
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
Array.from(document.querySelectorAll('script')).filter(el => !el.dataset.spaccdotweb).forEach(scriptElement => {
|
Build.BuildHtml(document.documentElement.outerHTML, {}).then(html => {
|
||||||
scriptElement.textContent = BuildScript(scriptElement.textContent).minified;
|
$('html').textContent = html;
|
||||||
|
document.querySelector('fieldset.html > span').innerHTML += `, ${html.length}b`;
|
||||||
});
|
});
|
||||||
$('html').textContent = `<!DOCTYPE html>\n${document.documentElement.outerHTML}`;
|
}, 1);
|
||||||
}, 100);
|
|
||||||
|
|
||||||
document.querySelectorAll('fieldset.script').forEach(fieldset => {
|
document.querySelectorAll('fieldset.script').forEach(fieldset => {
|
||||||
const script = fieldset.querySelector('textarea').textContent;
|
const script = fieldset.querySelector('textarea').textContent;
|
||||||
fieldset.querySelector('span').innerHTML += `, ${script.length}b`;
|
fieldset.querySelector('span').innerHTML += `, ${script.length}b`;
|
||||||
fieldset.appendChild(Object.assign(document.createElement('button'), {
|
fieldset.appendChild(createElement('button', {
|
||||||
innerHTML: "Execute",
|
innerHTML: "Execute",
|
||||||
onclick: () => eval(script),
|
onclick: () => eval(script),
|
||||||
}));
|
}));
|
||||||
|
@ -34,35 +34,49 @@ const babelConfig = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const findPath = (path, folder) => {
|
const findPath = (path, folder, files) => {
|
||||||
for (const prefix of [folder, __dirname]) {
|
for (const prefix of [folder, (typeof __dirname !== 'undefined' ? __dirname : '')]) {
|
||||||
path = Lib.path.join(prefix, path);
|
path = (Lib.path?.join(prefix, path) || `${prefix}/${path}`);
|
||||||
if (Lib.fs.existsSync(path)) {
|
if ((files && (path in files)) || (!files && Lib.fs?.existsSync(path))) {
|
||||||
return 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 isUrlAbsolute = (url) => (url && ['http:', 'https:', ''].includes(url.split('/')[0]));
|
||||||
|
|
||||||
const BuildScript = (scriptText, options) => {
|
const BuildScript = (scriptText, options) => {
|
||||||
options = {
|
options ||= {};
|
||||||
minify: true,
|
options.minify ??= true;
|
||||||
...options };
|
|
||||||
const compiled = (Lib.babel.transformSync || Lib.babel.transform)(scriptText, babelConfig).code;
|
const compiled = (Lib.babel.transformSync || Lib.babel.transform)(scriptText, babelConfig).code;
|
||||||
const minified = (options.minify && Lib.uglify.minify(compiled).code);
|
const minified = (options.minify && Lib.uglify.minify(compiled).code);
|
||||||
return { compiled, minified };
|
return { compiled, minified };
|
||||||
}
|
};
|
||||||
|
|
||||||
const BuildHtml = async (html, options) => {
|
const BuildStyle = async (styleText, stylePath, options) => {
|
||||||
options = {
|
options ||= {};
|
||||||
compileScripts: true,
|
options.minify ??= true;
|
||||||
minifyScripts: true,
|
const plugins = [
|
||||||
compileStyles: true,
|
Lib.postcssImport(),
|
||||||
inputFolder: '.',
|
Lib.postcssUrl({ url: 'inline' }),
|
||||||
...options };
|
...(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);
|
const dom = makeHtmlDom(html);
|
||||||
for (const element of dom.querySelectorAll('script, [src], link[rel=stylesheet][href]')) {
|
for (const element of dom.querySelectorAll('script, [src], link[rel=stylesheet][href]')) {
|
||||||
if (isUrlAbsolute(element.src || element.href)) {
|
if (isUrlAbsolute(element.src || element.href)) {
|
||||||
@ -72,21 +86,20 @@ const BuildHtml = async (html, options) => {
|
|||||||
const scriptOptions = JSON.parse(element.dataset.spaccdotweb || '{}');
|
const scriptOptions = JSON.parse(element.dataset.spaccdotweb || '{}');
|
||||||
const minifyScripts = (scriptOptions.minify ?? options.minifyScripts);
|
const minifyScripts = (scriptOptions.minify ?? options.minifyScripts);
|
||||||
let scriptText = (element.src
|
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);
|
: element.textContent);
|
||||||
if (scriptOptions.compile ?? options.compileScripts) {
|
if (scriptOptions.compile ?? options.compileScripts) {
|
||||||
scriptText = BuildScript(scriptText, { minify: minifyScripts })[minifyScripts ? 'minified' : 'compiled'];
|
scriptText = BuildScript(scriptText, { minify: minifyScripts })[minifyScripts ? 'minified' : 'compiled'];
|
||||||
}
|
}
|
||||||
|
if (scriptText) {
|
||||||
element.removeAttribute('src');
|
element.removeAttribute('src');
|
||||||
element.textContent = scriptText;
|
element.textContent = scriptText;
|
||||||
|
}
|
||||||
} else if (element.tagName === 'LINK') {
|
} else if (element.tagName === 'LINK') {
|
||||||
const stylePath = findPath(element.href, options.inputFolder);
|
const stylePath = findPath(element.href, options.inputFolder);
|
||||||
let styleText = Lib.fs.readFileSync(stylePath, 'utf8');
|
let styleText = readFile(stylePath, options.inputFolder, files); //Lib.fs.readFileSync(stylePath, 'utf8');
|
||||||
if (options.compileStyles) {
|
if (options.compileStyles && !envIsBrowser) {
|
||||||
styleText = (await Lib.postcss([
|
styleText = await BuildStyle(styleText, stylePath, { minify: options.minifyStyles });
|
||||||
Lib.postcssImport(),
|
|
||||||
Lib.postcssUrl({ url: 'inline' }),
|
|
||||||
]).process(styleText, { from: stylePath })).css;
|
|
||||||
}
|
}
|
||||||
element.parentElement.insertBefore(Object.assign(dom.createElement('style'), { textContent: styleText }), element);
|
element.parentElement.insertBefore(Object.assign(dom.createElement('style'), { textContent: styleText }), element);
|
||||||
element.remove();
|
element.remove();
|
||||||
@ -95,7 +108,7 @@ const BuildHtml = async (html, options) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return `<!DOCTYPE html>\n${dom.documentElement.outerHTML}`;
|
return `<!DOCTYPE html>\n${dom.documentElement.outerHTML}`;
|
||||||
}
|
};
|
||||||
|
|
||||||
return { BuildScript, BuildHtml, fileToBase64 };
|
return { BuildScript, BuildHtml, fileToBase64 };
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ const Lib = {
|
|||||||
babel: require('@babel/core'),
|
babel: require('@babel/core'),
|
||||||
uglify: require('uglify-js'),
|
uglify: require('uglify-js'),
|
||||||
postcss: require('postcss'),
|
postcss: require('postcss'),
|
||||||
|
postcssMinify: require('postcss-minify'),
|
||||||
postcssImport: require('postcss-import'),
|
postcssImport: require('postcss-import'),
|
||||||
postcssUrl: require('postcss-url'),
|
postcssUrl: require('postcss-url'),
|
||||||
jsdom: require('jsdom').JSDOM,
|
jsdom: require('jsdom').JSDOM,
|
||||||
@ -41,11 +42,10 @@ const BuildScriptFile = (scriptFile, options) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const BuildHtmlFile = (htmlFile, options) => {
|
const BuildHtmlFile = (htmlFile, options) => {
|
||||||
options = {
|
options ||= {};
|
||||||
outputFolder: './Build',
|
options.outputFile ??= htmlFile;
|
||||||
outputFile: htmlFile,
|
options.inputFolder ??= Lib.path.dirname(htmlFile);
|
||||||
inputFolder: Lib.path.dirname(htmlFile),
|
options.outputFolder ??= './Build';
|
||||||
...options };
|
|
||||||
const outputPath = `${options.outputFolder}/${options.outputFile}`;
|
const outputPath = `${options.outputFolder}/${options.outputFile}`;
|
||||||
Build.BuildHtml(Lib.fs.readFileSync(htmlFile, 'utf8'), options).then(html => Lib.fs.writeFileSync(outputPath, html));
|
Build.BuildHtml(Lib.fs.readFileSync(htmlFile, 'utf8'), options).then(html => Lib.fs.writeFileSync(outputPath, html));
|
||||||
return outputPath;
|
return outputPath;
|
||||||
@ -60,5 +60,5 @@ const EncodeStaticFiles = (files, /* encoding='base64' */) => {
|
|||||||
module.exports = Build = { ...Build, BuildScriptFile, BuildHtmlFile, EncodeStaticFiles };
|
module.exports = Build = { ...Build, BuildScriptFile, BuildHtmlFile, EncodeStaticFiles };
|
||||||
|
|
||||||
if (require.main === module) {
|
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
1444
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@ -17,13 +17,24 @@
|
|||||||
"jsdom": "^22.1.0",
|
"jsdom": "^22.1.0",
|
||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.3",
|
||||||
"postcss-import": "^16.1.0",
|
"postcss-import": "^16.1.0",
|
||||||
|
"postcss-minify": "^1.1.0",
|
||||||
"postcss-url": "^10.1.3",
|
"postcss-url": "^10.1.3",
|
||||||
"uglify-js": "^3.17.4",
|
"uglify-js": "^3.17.4",
|
||||||
"uglifyjs-browser": "^3.0.0"
|
"uglifyjs-browser": "^3.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"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": "^2.1.35",
|
||||||
"mime-types-browser": "^0.0.3",
|
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user