chore: unCRLF

This commit is contained in:
CanadaHonk 2022-12-09 18:03:36 +00:00
parent d605f783af
commit 9aa70d3131
11 changed files with 462 additions and 462 deletions

12
.gitignore vendored
View File

@ -1,7 +1,7 @@
# node
node_modules
package-lock.json
# gluon
build
# node
node_modules
package-lock.json
# gluon
build
chrome_data

40
LICENSE
View File

@ -1,21 +1,21 @@
MIT License
Copyright (c) 2022 OpenAsar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
MIT License
Copyright (c) 2022 OpenAsar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,47 +1,47 @@
# Gluon
Minimal integrated ecosystem for making "desktop apps" from websites easily using Chromium and NodeJS. Uses system installed Chromium and NodeJS, with optional bundling if you want that too (soon). ***VERY*** early and probably never finished/production ready. Doesn't use WebView2.
<br>
## Ecosystem
- [Gluon](gluon): the Gluon library (NodeJS)
- [Glugun](glugun): builds Gluon apps into releasable builds with optional bundling (soon)
### Apps
- [Gluworld](gluworld): basic Hello World demo app
- [Glucord](glucord): minimal desktop Discord client loading official webapp (demo/example)
<br>
## Release Schedule
Gluon (and it's subprojects) use a `major.patch` version format, with major releases being released daily if there are changes present in `main`, while using `X.0-dev` in the meantime. Patch releases may happen inbetween to fix bugs (not adding anything new or breaking).
<br>
## Comparisons
### Internals
| Part | Gluon | Electron | Tauri | Neutralinojs |
| ---- | ----- | -------- | ------------ | ----- |
| Frontend | System installed Chromium | Self-contained Chromium | System installed webview | System installed webview |
| Backend | System installed Node.JS | Self-contained Node.JS | Native (Rust) | Native (Any) |
| IPC | None (WIP) | Preload | Window object | Window object |
| Status | Early in development | "Production ready" | Usable | Usable |
| Ecosystem | Integrated | Distributed | Integrated | Integrated |
### Benchmark / Stats
Basic (plain HTML) Hello World demo, measured on up to date Windows 10. Used latest stable versions of all frameworks as of 9th Dec 2022.
| Stat | Gluon | Electron | Tauri | Neutralinojs |
| ---- | ----- | -------- | ------------ | ----- |
| Build Size | ~0.5MB[^system][^gluon][^1] | ~190MB | ~1.8MB[^system] | ~2.6MB[^system] |
| Memory Usage | ~90MB[^gluon] | ~100MB | ~90MB | ~90MB |
| Backend[^2] Memory Usage | ~13MB[^gluon] | ~22MB | ~3MB | ~3MB |
*Extra info: All HTML/CSS/JS is unminified (including Gluon). Built in release configuration. All binaries were left as compiled with common size optimizations enabled for that language, no stripping/packing done.*
[^system]: Does not include system installed components.
[^gluon]: Early/WIP data, may change in future.
[^1]: *How is Gluon so small?* Since NodeJS is expected as a system installed component, it is "just" bundled and minified Node code.
# Gluon
Minimal integrated ecosystem for making "desktop apps" from websites easily using Chromium and NodeJS. Uses system installed Chromium and NodeJS, with optional bundling if you want that too (soon). ***VERY*** early and probably never finished/production ready. Doesn't use WebView2.
<br>
## Ecosystem
- [Gluon](gluon): the Gluon library (NodeJS)
- [Glugun](glugun): builds Gluon apps into releasable builds with optional bundling (soon)
### Apps
- [Gluworld](gluworld): basic Hello World demo app
- [Glucord](glucord): minimal desktop Discord client loading official webapp (demo/example)
<br>
## Release Schedule
Gluon (and it's subprojects) use a `major.patch` version format, with major releases being released daily if there are changes present in `main`, while using `X.0-dev` in the meantime. Patch releases may happen inbetween to fix bugs (not adding anything new or breaking).
<br>
## Comparisons
### Internals
| Part | Gluon | Electron | Tauri | Neutralinojs |
| ---- | ----- | -------- | ------------ | ----- |
| Frontend | System installed Chromium | Self-contained Chromium | System installed webview | System installed webview |
| Backend | System installed Node.JS | Self-contained Node.JS | Native (Rust) | Native (Any) |
| IPC | None (WIP) | Preload | Window object | Window object |
| Status | Early in development | "Production ready" | Usable | Usable |
| Ecosystem | Integrated | Distributed | Integrated | Integrated |
### Benchmark / Stats
Basic (plain HTML) Hello World demo, measured on up to date Windows 10. Used latest stable versions of all frameworks as of 9th Dec 2022.
| Stat | Gluon | Electron | Tauri | Neutralinojs |
| ---- | ----- | -------- | ------------ | ----- |
| Build Size | ~0.5MB[^system][^gluon][^1] | ~190MB | ~1.8MB[^system] | ~2.6MB[^system] |
| Memory Usage | ~90MB[^gluon] | ~100MB | ~90MB | ~90MB |
| Backend[^2] Memory Usage | ~13MB[^gluon] | ~22MB | ~3MB | ~3MB |
*Extra info: All HTML/CSS/JS is unminified (including Gluon). Built in release configuration. All binaries were left as compiled with common size optimizations enabled for that language, no stripping/packing done.*
[^system]: Does not include system installed components.
[^gluon]: Early/WIP data, may change in future.
[^1]: *How is Gluon so small?* Since NodeJS is expected as a system installed component, it is "just" bundled and minified Node code.
[^2]: Backend like non-Web (not Chromium/WebView2/etc).

View File

@ -1,17 +1,17 @@
# Glucord
A minimal Discord client loading Discord Web, using system-installed Chromium/Node. Example/demo of Gluon.
<br>
## Testing
> **Note** |
> Gluon is currently **Windows only**.
1. Have recentish Chrome Stable/Canary and NodeJS installed
1. Clone the Gluon repo
2. `npm install` in `gluon`
3. `node glucord` (in repo root)
## Building
1. Cd into the repo root
# Glucord
A minimal Discord client loading Discord Web, using system-installed Chromium/Node. Example/demo of Gluon.
<br>
## Testing
> **Note** |
> Gluon is currently **Windows only**.
1. Have recentish Chrome Stable/Canary and NodeJS installed
1. Clone the Gluon repo
2. `npm install` in `gluon`
3. `node glucord` (in repo root)
## Building
1. Cd into the repo root
2. `node glugun glucord glucord`

File diff suppressed because one or more lines are too long

View File

@ -1,116 +1,116 @@
import { cp, writeFile, readFile, readdir, rm, mkdir, stat, access } from 'fs/promises';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import * as Esbuild from 'esbuild';
import * as HTMLMinifier from 'html-minifier-terser';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`;
const log = (...args) => console.log(`[${rgb(235, 69, 158, 'Glugun')}]`, ...args);
const minifyBackend = process.argv.includes('--minify');
const esbuildPlugin = { // esbuild to fix some things in src files
name: 'glugun-esbuild',
setup(build) {
build.onLoad({ filter: /\.js$/ }, async (args) => {
let source = await readFile(args.path, 'utf8');
source = source
.replace(`const __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = dirname(__filename);`, ''); // remove setting __filename/__dirname cause ESM -> CJS
return { contents: source };
});
}
};
const exists = path => access(path).then(() => true).catch(() => false);
const dirSize = async dir => {
const files = await readdir(dir, { withFileTypes: true });
const paths = files.map(async file => {
const path = join(dir, file.name);
if (file.isDirectory()) return await dirSize(path);
if (file.isFile()) return (await stat(path)).size;
return 0;
});
return (await Promise.all(paths)).flat(Infinity).reduce((acc, x) => acc + x, 0);
};
const buildDir = join(__dirname, '..', 'build');
const _buildWin32 = async (name, dir, attrs) => {
// reset build dir
await rm(buildDir, { recursive: true, force: true });
await mkdir(buildDir, { recursive: true });
await cp(dir, join(buildDir, 'src'), { recursive: true }); // copy project src to build
await cp(join(__dirname, '..', 'gluon'), join(buildDir, 'src', 'gluon'), { recursive: true }); // copy gluon into build
for (const m of [ 'ws', 'chrome-remote-interface' ]) {
const dest = join(buildDir, 'src', 'node_modules', m);
await cp(join(__dirname, '..', 'node_modules', m), dest, { recursive: true }); // copy gluon deps into build
for (const x of await readdir(dest)) {
if ([ 'bin', 'README.md', 'webpack.config.json', 'browser.js' ].includes(x)) await rm(join(dest, x), { recursive: true });
}
}
// await writeFile(join(buildDir, 'gluon_info.txt'), `Gluon 0.1, built with Glugun 0.1 (win32 ${attrs.join(',')})`);
let indexContent = await readFile(join(buildDir, 'src', 'index.js'), 'utf8');
indexContent = indexContent.replace('../gluon/', './gluon/')
.replaceAll('GLUGUN_VERSION', '2.1')
.replaceAll('SYSTEM_CHROMIUM', attrs.includes('system-chromium'))
.replaceAll('SYSTEM_NODE', attrs.includes('system-node'));
await writeFile(join(buildDir, 'src', 'index.js'), indexContent);
await writeFile(join(buildDir, `${name}.bat`), `node %~dp0${minifyBackend ? 'out.js' : 'src'}`);
if (minifyBackend) {
log(`pre-minify build size: ${((await dirSize(buildDir)) / 1024 / 1024).toFixed(2)}MB`);
await Esbuild.build({ // bundle and minify into 1 file
entryPoints: [ join(buildDir, 'src', 'index.js') ],
bundle: true,
minify: true,
format: 'iife',
platform: 'node',
outfile: join(buildDir, 'out.js'),
plugins: [ esbuildPlugin ]
});
const htmlPath = join(buildDir, 'src', 'index.html');
if (await exists(htmlPath)) {
const content = await readFile(htmlPath, 'utf8');
writeFile(join(buildDir, 'index.html'), await HTMLMinifier.minify(content));
}
await rm(join(buildDir, 'src'), { recursive: true }); // delete original src
}
};
export const build = async (name, dir, platform = 'win32', attrs = 'system-chromium,system-node') => {
log('building', name, 'on', platform, 'with', attrs.split(',').join(', ') + '...');
console.log();
const startTime = performance.now();
switch (platform) {
case 'win32': await _buildWin32(name, dir, attrs.split(','));
}
console.log();
log(`finished build in: ${((performance.now() - startTime) / 1024).toFixed(2)}s`);
log(`final build size: ${((await dirSize(buildDir)) / 1024 / 1024).toFixed(2)}MB`);
};
const [ name, dir ] = process.argv.slice(2);
import { cp, writeFile, readFile, readdir, rm, mkdir, stat, access } from 'fs/promises';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import * as Esbuild from 'esbuild';
import * as HTMLMinifier from 'html-minifier-terser';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`;
const log = (...args) => console.log(`[${rgb(235, 69, 158, 'Glugun')}]`, ...args);
const minifyBackend = process.argv.includes('--minify');
const esbuildPlugin = { // esbuild to fix some things in src files
name: 'glugun-esbuild',
setup(build) {
build.onLoad({ filter: /\.js$/ }, async (args) => {
let source = await readFile(args.path, 'utf8');
source = source
.replace(`const __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);`, ''); // remove setting __filename/__dirname cause ESM -> CJS
return { contents: source };
});
}
};
const exists = path => access(path).then(() => true).catch(() => false);
const dirSize = async dir => {
const files = await readdir(dir, { withFileTypes: true });
const paths = files.map(async file => {
const path = join(dir, file.name);
if (file.isDirectory()) return await dirSize(path);
if (file.isFile()) return (await stat(path)).size;
return 0;
});
return (await Promise.all(paths)).flat(Infinity).reduce((acc, x) => acc + x, 0);
};
const buildDir = join(__dirname, '..', 'build');
const _buildWin32 = async (name, dir, attrs) => {
// reset build dir
await rm(buildDir, { recursive: true, force: true });
await mkdir(buildDir, { recursive: true });
await cp(dir, join(buildDir, 'src'), { recursive: true }); // copy project src to build
await cp(join(__dirname, '..', 'gluon'), join(buildDir, 'src', 'gluon'), { recursive: true }); // copy gluon into build
for (const m of [ 'ws', 'chrome-remote-interface' ]) {
const dest = join(buildDir, 'src', 'node_modules', m);
await cp(join(__dirname, '..', 'node_modules', m), dest, { recursive: true }); // copy gluon deps into build
for (const x of await readdir(dest)) {
if ([ 'bin', 'README.md', 'webpack.config.json', 'browser.js' ].includes(x)) await rm(join(dest, x), { recursive: true });
}
}
// await writeFile(join(buildDir, 'gluon_info.txt'), `Gluon 0.1, built with Glugun 0.1 (win32 ${attrs.join(',')})`);
let indexContent = await readFile(join(buildDir, 'src', 'index.js'), 'utf8');
indexContent = indexContent.replace('../gluon/', './gluon/')
.replaceAll('GLUGUN_VERSION', '2.1')
.replaceAll('SYSTEM_CHROMIUM', attrs.includes('system-chromium'))
.replaceAll('SYSTEM_NODE', attrs.includes('system-node'));
await writeFile(join(buildDir, 'src', 'index.js'), indexContent);
await writeFile(join(buildDir, `${name}.bat`), `node %~dp0${minifyBackend ? 'out.js' : 'src'}`);
if (minifyBackend) {
log(`pre-minify build size: ${((await dirSize(buildDir)) / 1024 / 1024).toFixed(2)}MB`);
await Esbuild.build({ // bundle and minify into 1 file
entryPoints: [ join(buildDir, 'src', 'index.js') ],
bundle: true,
minify: true,
format: 'iife',
platform: 'node',
outfile: join(buildDir, 'out.js'),
plugins: [ esbuildPlugin ]
});
const htmlPath = join(buildDir, 'src', 'index.html');
if (await exists(htmlPath)) {
const content = await readFile(htmlPath, 'utf8');
writeFile(join(buildDir, 'index.html'), await HTMLMinifier.minify(content));
}
await rm(join(buildDir, 'src'), { recursive: true }); // delete original src
}
};
export const build = async (name, dir, platform = 'win32', attrs = 'system-chromium,system-node') => {
log('building', name, 'on', platform, 'with', attrs.split(',').join(', ') + '...');
console.log();
const startTime = performance.now();
switch (platform) {
case 'win32': await _buildWin32(name, dir, attrs.split(','));
}
console.log();
log(`finished build in: ${((performance.now() - startTime) / 1024).toFixed(2)}s`);
log(`final build size: ${((await dirSize(buildDir)) / 1024 / 1024).toFixed(2)}MB`);
};
const [ name, dir ] = process.argv.slice(2);
build(name, dir);

View File

@ -1,7 +1,7 @@
{
"type": "module",
"dependencies": {
"esbuild": "^0.16.3",
"html-minifier-terser": "^7.1.0"
}
{
"type": "module",
"dependencies": {
"esbuild": "^0.16.3",
"html-minifier-terser": "^7.1.0"
}
}

View File

@ -1,100 +1,100 @@
const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`;
const log = (...args) => console.log(`[${rgb(88, 101, 242, 'Gluon')}]`, ...args);
process.versions.gluon = '2.1';
const presets = { // Presets from OpenAsar
'base': '--autoplay-policy=no-user-gesture-required --disable-features=WinRetrieveSuggestionsOnlyOnDemand,HardwareMediaKeyHandling,MediaSessionService', // Base Discord
'perf': '--enable-gpu-rasterization --enable-zero-copy --ignore-gpu-blocklist --enable-hardware-overlays=single-fullscreen,single-on-top,underlay --enable-features=EnableDrDc,CanvasOopRasterization,BackForwardCache:TimeToLiveInBackForwardCacheInSeconds/300/should_ignore_blocklists/true/enable_same_site/true,ThrottleDisplayNoneAndVisibilityHiddenCrossOriginIframes,UseSkiaRenderer,WebAssemblyLazyCompilation --disable-features=Vulkan --force_high_performance_gpu', // Performance
'battery': '--enable-features=TurnOffStreamingMediaCachingOnBattery --force_low_power_gpu', // Known to have better battery life for Chromium?
'memory': '--in-process-gpu --js-flags="--lite-mode --optimize_for_size --wasm_opt --wasm_lazy_compilation --wasm_lazy_validation --always_compact" --renderer-process-limit=2 --enable-features=QuickIntensiveWakeUpThrottlingAfterLoading' // Less (?) memory usage
};
import { exec } from 'child_process';
import { join, dirname } from 'path';
import { access } from 'fs/promises';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
import CDP from 'chrome-remote-interface';
const chromiumPathsWin = {
stable: join(process.env.PROGRAMFILES, 'Google', 'Chrome', 'Application', 'chrome.exe'),
canary: join(process.env.LOCALAPPDATA, 'Google', 'Chrome SxS', 'Application', 'chrome.exe'),
edge: join(process.env['PROGRAMFILES(x86)'], 'Microsoft', 'Edge', 'Application', 'msedge.exe')
};
const exists = path => access(path).then(() => true).catch(() => false);
const findChromiumPath = async () => {
let whichChromium = '';
for (const x of [ 'stable', 'canary', 'edge' ]) {
if (process.argv.includes('--' + x)) whichChromium = x;
}
if (!whichChromium) {
for (const x in chromiumPathsWin) {
log(x, chromiumPathsWin[x], await exists(chromiumPathsWin[x]));
if (await exists(chromiumPathsWin[x])) {
whichChromium = x;
break;
}
}
}
if (!whichChromium) return null;
return chromiumPathsWin[whichChromium];
};
const getDataPath = () => join(__dirname, '..', 'chrome_data');
const startChromium = (url, { windowSize }) => new Promise(async res => {
const dataPath = getDataPath();
const chromiumPath = await findChromiumPath();
log('chromium path:', chromiumPath);
log('data path:', dataPath);
if (!chromiumPath) return log('failed to find a good chromium install');
const debugPort = 9222;
exec(`"${chromiumPath}" --app=${url} --remote-debugging-port=${debugPort} --user-data-dir="${dataPath}" ${windowSize ? `--window-size=${windowSize.join(',')}` : ''} --new-window --disable-extensions --disable-default-apps --disable-breakpad --disable-crashpad --disable-background-networking --disable-domain-reliability --disable-component-update --disable-sync --disable-features=AutofillServerCommunication ${presets.perf}`, (err, stdout, stderr) => {
log(err, stdout, stderr);
});
setTimeout(() => res(debugPort), 500);
});
export const open = async (url, onLoad = () => {}, { windowSize } = {}) => {
log('starting chromium...');
const debugPort = await startChromium(url, { windowSize });
log('connecting to CDP...');
const { Runtime, Page } = await CDP({ port: debugPort });
// const run = async js => (await Runtime.evaluate({ expression: js })).result.value;
const run = async js => log(await Runtime.evaluate({ expression: js }));
const toRun = `(() => {
if (window.self !== window.top) return; // inside frame
const GLUON_VERSION = '${process.versions.gluon}';
const NODE_VERSION = '${process.versions.node}';
const CHROMIUM_VERSION = navigator.userAgentData.brands.find(x => x.brand === "Chromium").version;
(${onLoad.toString()})();
})()`;
run(toRun);
await Page.enable();
await Page.addScriptToEvaluateOnNewDocument({ source: toRun });
};
const rgb = (r, g, b, msg) => `\x1b[38;2;${r};${g};${b}m${msg}\x1b[0m`;
const log = (...args) => console.log(`[${rgb(88, 101, 242, 'Gluon')}]`, ...args);
process.versions.gluon = '2.1';
const presets = { // Presets from OpenAsar
'base': '--autoplay-policy=no-user-gesture-required --disable-features=WinRetrieveSuggestionsOnlyOnDemand,HardwareMediaKeyHandling,MediaSessionService', // Base Discord
'perf': '--enable-gpu-rasterization --enable-zero-copy --ignore-gpu-blocklist --enable-hardware-overlays=single-fullscreen,single-on-top,underlay --enable-features=EnableDrDc,CanvasOopRasterization,BackForwardCache:TimeToLiveInBackForwardCacheInSeconds/300/should_ignore_blocklists/true/enable_same_site/true,ThrottleDisplayNoneAndVisibilityHiddenCrossOriginIframes,UseSkiaRenderer,WebAssemblyLazyCompilation --disable-features=Vulkan --force_high_performance_gpu', // Performance
'battery': '--enable-features=TurnOffStreamingMediaCachingOnBattery --force_low_power_gpu', // Known to have better battery life for Chromium?
'memory': '--in-process-gpu --js-flags="--lite-mode --optimize_for_size --wasm_opt --wasm_lazy_compilation --wasm_lazy_validation --always_compact" --renderer-process-limit=2 --enable-features=QuickIntensiveWakeUpThrottlingAfterLoading' // Less (?) memory usage
};
import { exec } from 'child_process';
import { join, dirname } from 'path';
import { access } from 'fs/promises';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
import CDP from 'chrome-remote-interface';
const chromiumPathsWin = {
stable: join(process.env.PROGRAMFILES, 'Google', 'Chrome', 'Application', 'chrome.exe'),
canary: join(process.env.LOCALAPPDATA, 'Google', 'Chrome SxS', 'Application', 'chrome.exe'),
edge: join(process.env['PROGRAMFILES(x86)'], 'Microsoft', 'Edge', 'Application', 'msedge.exe')
};
const exists = path => access(path).then(() => true).catch(() => false);
const findChromiumPath = async () => {
let whichChromium = '';
for (const x of [ 'stable', 'canary', 'edge' ]) {
if (process.argv.includes('--' + x)) whichChromium = x;
}
if (!whichChromium) {
for (const x in chromiumPathsWin) {
log(x, chromiumPathsWin[x], await exists(chromiumPathsWin[x]));
if (await exists(chromiumPathsWin[x])) {
whichChromium = x;
break;
}
}
}
if (!whichChromium) return null;
return chromiumPathsWin[whichChromium];
};
const getDataPath = () => join(__dirname, '..', 'chrome_data');
const startChromium = (url, { windowSize }) => new Promise(async res => {
const dataPath = getDataPath();
const chromiumPath = await findChromiumPath();
log('chromium path:', chromiumPath);
log('data path:', dataPath);
if (!chromiumPath) return log('failed to find a good chromium install');
const debugPort = 9222;
exec(`"${chromiumPath}" --app=${url} --remote-debugging-port=${debugPort} --user-data-dir="${dataPath}" ${windowSize ? `--window-size=${windowSize.join(',')}` : ''} --new-window --disable-extensions --disable-default-apps --disable-breakpad --disable-crashpad --disable-background-networking --disable-domain-reliability --disable-component-update --disable-sync --disable-features=AutofillServerCommunication ${presets.perf}`, (err, stdout, stderr) => {
log(err, stdout, stderr);
});
setTimeout(() => res(debugPort), 500);
});
export const open = async (url, onLoad = () => {}, { windowSize } = {}) => {
log('starting chromium...');
const debugPort = await startChromium(url, { windowSize });
log('connecting to CDP...');
const { Runtime, Page } = await CDP({ port: debugPort });
// const run = async js => (await Runtime.evaluate({ expression: js })).result.value;
const run = async js => log(await Runtime.evaluate({ expression: js }));
const toRun = `(() => {
if (window.self !== window.top) return; // inside frame
const GLUON_VERSION = '${process.versions.gluon}';
const NODE_VERSION = '${process.versions.node}';
const CHROMIUM_VERSION = navigator.userAgentData.brands.find(x => x.brand === "Chromium").version;
(${onLoad.toString()})();
})()`;
run(toRun);
await Page.enable();
await Page.addScriptToEvaluateOnNewDocument({ source: toRun });
};

View File

@ -1,6 +1,6 @@
{
"type": "module",
"dependencies": {
"chrome-remote-interface": "^0.31.3"
}
}
{
"type": "module",
"dependencies": {
"chrome-remote-interface": "^0.31.3"
}
}

View File

@ -1,78 +1,78 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link rel="icon" href="https://raw.githubusercontent.com/OpenAsar/gluon/main/assets/logo.png">
<title>Gluworld</title>
</head>
<body>
<h1>
Gluon <code id="gluon_version"></code> <br>
built with <code id="glugun_version"></code>
</h1>
<div id="versions">
<h2>
Chromium <br>
<code id="chromium_version"></code>
</h2>
<h2>
Node <br>
<code id="node_version"></code>
</h2>
</div>
<style>
/* @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=Roboto:ital,wght@0,400;0,700;1,500&display=swap'); */
@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&family=Inter:wght@300;400;500;600;700;800;900');
html, body {
background: #101418;
color: #fff;
font-family: Inter, sans-serif;
}
body {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90%;
padding: 12px;
}
h1, h2, code {
text-align: center;
}
h1 {
font-weight: 900;
font-size: 34px;
}
h1 > code {
margin-left: 8px;
}
h2 {
font-weight: 800;
font-size: 28px;
}
code {
font-size: 100%;
font-family: Fira Code;
}
#versions {
display: flex;
justify-content: space-around;
width: 100%;
margin-top: 20vh;
}
</style>
</body>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link rel="icon" href="https://raw.githubusercontent.com/OpenAsar/gluon/main/assets/logo.png">
<title>Gluworld</title>
</head>
<body>
<h1>
Gluon <code id="gluon_version"></code> <br>
built with <code id="glugun_version"></code>
</h1>
<div id="versions">
<h2>
Chromium <br>
<code id="chromium_version"></code>
</h2>
<h2>
Node <br>
<code id="node_version"></code>
</h2>
</div>
<style>
/* @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=Roboto:ital,wght@0,400;0,700;1,500&display=swap'); */
@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&family=Inter:wght@300;400;500;600;700;800;900');
html, body {
background: #101418;
color: #fff;
font-family: Inter, sans-serif;
}
body {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90%;
padding: 12px;
}
h1, h2, code {
text-align: center;
}
h1 {
font-weight: 900;
font-size: 34px;
}
h1 > code {
margin-left: 8px;
}
h2 {
font-weight: 800;
font-size: 28px;
}
code {
font-size: 100%;
font-family: Fira Code;
}
#versions {
display: flex;
justify-content: space-around;
width: 100%;
margin-top: 20vh;
}
</style>
</body>
</html>

View File

@ -1,22 +1,22 @@
import * as Gluon from '../gluon/index.js';
import { fileURLToPath, pathToFileURL } from 'url';
import { join, dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
Gluon.open(pathToFileURL(join(__dirname, 'index.html')).href, () => {
const setVersions = () => {
if (typeof chromium_version === 'undefined') return setTimeout(setVersions, 100);
chromium_version.textContent = CHROMIUM_VERSION;
node_version.textContent = NODE_VERSION;
gluon_version.textContent = GLUON_VERSION;
glugun_version.textContent = 'GLUGUN_VERSION' === 'G\LUGUN_VERSION' ? 'nothing' : 'Glugun GLUGUN_VERSION';
};
setVersions();
}, {
windowSize: [ 800, 450 ]
import * as Gluon from '../gluon/index.js';
import { fileURLToPath, pathToFileURL } from 'url';
import { join, dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
Gluon.open(pathToFileURL(join(__dirname, 'index.html')).href, () => {
const setVersions = () => {
if (typeof chromium_version === 'undefined') return setTimeout(setVersions, 100);
chromium_version.textContent = CHROMIUM_VERSION;
node_version.textContent = NODE_VERSION;
gluon_version.textContent = GLUON_VERSION;
glugun_version.textContent = 'GLUGUN_VERSION' === 'G\LUGUN_VERSION' ? 'nothing' : 'Glugun GLUGUN_VERSION';
};
setVersions();
}, {
windowSize: [ 800, 450 ]
});