main
.container
h1 Tiny JavaScript Minifier
p.lead Using Google's Closure Compiler service
hr.my-4
.row.inputs
.col-sm-6
h4 Plop your JavaScript Here !
.input-group
textarea#input.form-control
| // ADD YOUR CODE HERE
| function hello(name) {
| alert('Hello, ' + name);
| }
| hello('New user');
.col-sm-6
h4 Get your compressed code here !
.input-group
textarea#output.form-control
small#stats Click the compile button to see stats !
#options
h4 You might want to specify some options...
a(href="https://developers.google.com/closure/compiler/docs/api-ref" target="_blank") (documentation)
button#go.btn.btn-outline-primary.btn-lg.d-block Compile !
hr.my-4
p
small
| Note: not all options are included here, this is supposed to be a small web app.
a(href="https://closure-compiler.appspot.com/home" target="_blank") Here
| is a more complex one.
#log
View Compiled
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
main {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
min-height: 100vh;
background: #eee;
.container {
margin: auto;
padding: 1em .8em;
box-sizing: border-box;
[class^='col-']{
margin-bottom: 1em;
}
#input,
#output {
min-height: 50px;
}
}
}
/**
* TODO
* add options to UI
* link the api reference
* auto hide advanced options (show/hide)
* add possibility of external file
* add compression factor
* add log (switch to json)
*/
/**
* XMLHTTP requests to the API
*/
function getURL(domain, params) {
if (domain.indexOf('?') === -1) domain += '?'
let keys = Object.keys(params)
for (key of keys) {
if (Array.isArray(params[key])) {
for (let i=0; i<params[key].length; i++) {
addParameter(params[key][i])
}
} else {
addParameter(params[key])
}
}
domain = domain.slice(0, -1)
return domain
function addParameter(param) {
domain += `${key}=${encodeURIComponent(param)}&`
}
}
function getData(url, callback) {
let xhttp = new XMLHttpRequest()
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
callback.call(window, xhttp.responseText)
}
}
xhttp.open('POST', url)
xhttp.withCredentials = false
xhttp.send()
}
/**
* UI Stuffs
*/
let DOM = {
go: document.getElementById('go'),
input: document.getElementById('input'),
output: document.getElementById('output'),
stats: document.getElementById('stats'),
log: document.getElementById('log'),
optionsWrapper: document.getElementById('options'),
options: {} // Different inputs generated in addOptionsToWrapper
}
/**
* Options initializer
*/
// Used for initalizing the options
const options = {
// js_code: 'function hello(name){alert("Hello, "+name)}hello("New user");',
// code_url: TEXTBOX
compilation_level: {
names: ['Whitespace', 'Simple', 'Advanced'],
values: ['WHITESPACE_ONLY', 'SIMPLE_OPTIMIZATIONS', 'ADVANCED_OPTIMIZATIONS'],
default: 'SIMPLE_OPTIMIZATIONS',
label: 'Compilation'
},
// output_format: {
// names: ['XML', 'JSON', 'Text'],
// values: ['xml', 'json', 'text'],
// default: 'text'
// },
// output_info: {
// names: ['Compiled code', 'Warnings', 'Errors', 'Statistics'],
// values: ['compiled_code', 'warnings', 'errors', 'statistics'],
// default: 'compiled_code',
// label: 'Output info'
// },
// js_externs: TEXTBOX
// externs_url: TEXTBOX
// exclude_default_externs: {
// names: ['Yes', 'No'],
// values: ['true', 'false'],
// default: 'false',
// label: 'Excluse default externs'
// },
// output_file_name: TEXTBOX
formatting: {
names: ['Pretty print', 'Print input delimiter'],
values: ['pretty_print', 'print_input_delimiter'],
default: 'print_input_delimiter',
label: 'Formatting'
},
// use_closure_library: {
// names: ['Yes', 'No'],
// values: ['true', 'false'],
// default: 'false',
// label: 'Use closure library'
// },
// warning_level: {
// names: ['Quiet', 'Default', 'Verbose'],
// values: ['QUIET', 'DEFAULT', 'VERBOSE'],
// default: 'DEFAULT',
// label: 'Warning level'
// },
language: {
names: ['ECMAScript 3', 'ECMAScript 5', 'ECMAScript 5 strict', 'ECMAScript 6', 'ECMAScript 6 strict'],
values: ['ECMASCRIPT3', 'ECMASCRIPT5', 'ECMASCRIPT5_STRICT', 'ECMASCRIPT6', 'ECMASCRIPT6_STRICT'],
default: 'ECMASCRIPT6',
label: 'Language in'
},
language_out: {
names: ['ECMAScript 3', 'ECMAScript 5', 'ECMAScript 5 strict', 'ECMAScript 6', 'ECMAScript 6 strict'],
values: ['ECMASCRIPT3', 'ECMASCRIPT5', 'ECMASCRIPT5_STRICT', 'ECMASCRIPT6', 'ECMASCRIPT6_STRICT'],
default: 'ECMASCRIPT5',
label: 'Language out'
}
}
function addOptionsToWrapper(options, wrapper, domOptions) {
let keys = Object.keys(options)
let row
for (let i=0; i<keys.length; i++) {
if (i%2 === 0) {
row = document.createElement('div')
row.classList.add('row')
wrapper.appendChild(row)
}
let col = document.createElement('div')
col.classList.add('col-sm-6')
let inputgroup = document.createElement('div')
inputgroup.classList.add('input-group')
let inputgroupprepend = document.createElement('div')
inputgroupprepend.classList.add('input-group-prepend')
let title = document.createElement('span')
title.classList.add('input-group-text')
title.innerHTML = options[keys[i]].label
let select = document.createElement('select')
select.classList.add('form-control')
domOptions[keys[i]] = select
let selectoptions = options[keys[i]]
for (let j=0; j<selectoptions.names.length; j++) {
let option = document.createElement('option')
option.value = selectoptions.values[j]
option.innerHTML = selectoptions.names[j]
select.appendChild(option)
}
select.value = selectoptions.default
inputgroupprepend.appendChild(title)
inputgroup.appendChild(inputgroupprepend)
inputgroup.appendChild(select)
col.appendChild(inputgroup)
row.appendChild(col)
}
}
// I used to have more options, but removed some for simplicity sakes
// This is why I build this function
addOptionsToWrapper(options, DOM.optionsWrapper, DOM.options)
/**
* Compiler
*/
DOM.go.onclick = function() {
this.disabled = true
this.innerHTML = 'Compiling...'
getData(getURL('https://closure-compiler.appspot.com/compile', {
js_code: DOM.input.value,
compilation_level: DOM.options.compilation_level.value,
output_format: 'json',
output_info: ['compiled_code', 'warnings', 'errors', 'statistics'],
// output_info: DOM.options.output_info.value,
// exclude_default_externs: DOM.options.exclude_default_externs.value,
formatting: DOM.options.formatting.value,
// use_closure_library: DOM.options.use_closure_library.value,
// warning_level: DOM.options.warning_level.value,
language: DOM.options.language.value,
language_out: DOM.options.language_out.value,
}), function(data) {
let parsed = JSON.parse(data)
let keys = Object.keys(parsed)
for (let i=0; i<keys.length; i++) {
switch(keys[i]) {
case 'compiledCode':
DOM.output.innerHTML = parsed.compiledCode
break
case 'statistics':
let s = parsed.statistics
DOM.stats.innerHTML = `Compressed ${s.originalSize} bytes down to ${s.compressedSize} bytes (${Math.round((s.originalSize-s.compressedSize)/s.originalSize*100)}%) in ${s.compileTime} ms`
break
default:
console.log(parsed[keys[i]])
break
}
}
DOM.go.disabled = false
DOM.go.innerHTML = 'Compile !'
})
}
View Compiled
This Pen doesn't use any external JavaScript resources.