Skip to content

Instantly share code, notes, and snippets.

@daveknights
Last active February 13, 2024 09:54
Show Gist options
  • Save daveknights/7e6124184c5d49f8498d6fa91fb21181 to your computer and use it in GitHub Desktop.
Save daveknights/7e6124184c5d49f8498d6fa91fb21181 to your computer and use it in GitHub Desktop.
Node js custom minifier for the Cre8bitJS library.
const events = require('events')
const fs = require('fs')
const readline = require('readline')
const a2z = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
const fileName = process.argv[2]
const varMin = [...a2z.slice(0, 13)]
const constMin = [...a2z.slice(0, 23)]
const letMin = [...a2z.slice(0, 10)]
const funcMin = [...a2z.slice(0, 7)]
const spacesAround = ['=', , '===', '=>', '+', '&&', '?', '>', '+=']
const spaceAfter = ['if', ':', ',']
const spaceBefore = ['(', '{', ':', '`']
const varNames = {}
let newData = '';
const processLineByLine = async () => {
try {
const rl = readline.createInterface({
input: fs.createReadStream(`../${fileName}.js`),
crlfDelay: Infinity
})
for await (let line of rl) {
for (const varName in varNames) {
// Replace #private & scoped vars and methods with short identifier
line.includes(varName) && (line = line.replace(new RegExp(varName, 'g'), varNames[varName]))
}
line = line.replace(/^\s+/, '')
// Remove unnecessary spaces only
if (!line.startsWith('/') && !line.startsWith('*')) {
for (const char of spacesAround) {
line = line.replace(` ${char} `, char)
}
for (const char of spaceAfter) {
line = line.replace(`${char} `, char)
}
for (const char of spaceBefore) {
line = line.replace(` ${char}`, char)
}
newData += line
}
}
// Remove occurrences of ; before } and ' * ' once all code is on one line
newData = newData.replaceAll(/\s\*\s/g, '*');
newData = newData.replaceAll(/;}/g, '}')
fs.writeFile(`../${fileName}.min.js`, newData, () => console.log('Minification complete'))
await events.once(rl, 'close')
} catch (err) {
console.error(err)
}
}
const getVars = async () => {
try {
const rl = readline.createInterface({
input: fs.createReadStream(`../${fileName}.js`),
crlfDelay: Infinity
})
let varInc = 0
let constInc = 0
let funcInc = 0
let letInc = 0
for await (let line of rl) {
line = line.replace(/^\s+/, '')
if (line.startsWith('#') && !line.includes('(')) {
const varName = line.split(' ')
varNames[varName[0]] = `#${varMin[varInc]}V`
varInc++
} else if (line.startsWith('const ')) {
const varName = line.match(/(?<=\s)(.*?)(?=\s)/)
varNames[varName[0]] = `${constMin[constInc]}C`
constInc++
} else if (line.startsWith('#') && line.includes('(')) {
const varName = line.split('(')
varNames[varName[0]] = `#${funcMin[funcInc]}F`
funcInc++
} else if (line.startsWith('let ')) {
const varName = line.match(/(?<=\s)(.*?)(?=\s)/)
varNames[varName[0]] = `${letMin[letInc]}L`
letInc++
}
}
processLineByLine()
} catch (err) {
console.error(err)
}
}
getVars()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment