forked from tahtituho/sikistys
-
Notifications
You must be signed in to change notification settings - Fork 0
/
compeko.js
78 lines (61 loc) · 3.04 KB
/
compeko.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// compeko - pack JavaScript into a self-extracting html+deflate
// v1.1.0
// Copyright (c) 2022 0b5vr
// SPDX-License-Identifier: MIT
// Usage:
// - prepare a js code, which will be fed into `eval`
// - install `node-zopfli` as your (dev-) dependency
// - run: `node compeko.js input.js output.html`
// Shoutouts to:
// - gasman, for pnginator ... https://gist.github.com/gasman/2560551
// - Charles Boccato, for JsExe ... https://www.pouet.net/prod.php?which=59298
// - subzey, for fetchcrunch ... https://github.com/subzey/fetchcrunch
// - Achieves almost the same concept. Referred several tricks of the header code
// Source: https://gist.github.com/0b5vr/09ee96ca2efbe5bf9d64dad7220e923b
// Small modifications made
// =================================================================================================
// -- sanity check ---------------------------------------------------------------------------------
try {
require( 'node-zopfli' );
} catch ( e ) {
console.error( e );
console.error( `
\x1b[31mMake sure you installed \x1b[35mnode-zopfli\x1b[31m !\x1b[0m` );
process.exit( 1 );
}
if ( process.argv[ 3 ] == null ) {
console.error( '\x1b[31mUsage: \x1b[35mnode compeko.js input.js output.html\x1b[0m' );
process.exit( 1 );
}
// -- modules --------------------------------------------------------------------------------------
const fs = require( 'fs' );
const { resolve } = require( 'path' );
const zopfli = require( 'node-zopfli' );
// -- main -----------------------------------------------------------------------------------------
console.info( 'Compressing the file...' );
( async () => {
const inputPath = resolve( process.cwd(), process.argv[ 2 ] );
const outputPath = resolve( process.cwd(), process.argv[ 3 ] );
const inputFile = await fs.promises.readFile( inputPath );
const inputSize = inputFile.length;
console.info( `Input size: \x1b[32m${ inputSize.toLocaleString() } bytes\x1b[0m` );
const compressed = await zopfli.deflate( inputFile, {
numiterations: 100, // increase this number to shave your last bytes
blocksplitting: true,
} );
// extra: output deflate
{
const outputPathBase = outputPath.match( /(.*)\..+$/ )[ 1 ];
const deflatePath = `${ outputPathBase }.deflate.bin`;
await fs.promises.writeFile( deflatePath, compressed );
}
const header = `<svg onload="fetch('#').then(t=>t.blob()).then(t=>new Response(t.slice(158).stream().pipeThrough(new DecompressionStream('deflate-raw'))).text()).then(eval)">`;
const headerBuffer = Buffer.alloc( header.length );
headerBuffer.write( header );
const concated = Buffer.concat( [ headerBuffer, compressed ] );
const outputSize = concated.length;
const percentage = ( 100.0 * ( outputSize / inputSize ) ).toFixed( 3 );
console.info( `Output size: \x1b[32m${ outputSize.toLocaleString() } bytes\x1b[0m (${ percentage } %)` );
await fs.promises.writeFile( outputPath, concated );
console.info( 'Done \x1b[32m✓\x1b[0m' );
} )();