Skip to content

Instantly share code, notes, and snippets.

@markusfisch
Last active January 15, 2016 17:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markusfisch/1894816 to your computer and use it in GitHub Desktop.
Save markusfisch/1894816 to your computer and use it in GitHub Desktop.
A little script that helps to generate a source archive for CSS/JavaScript files.

srcar

Helps you to generate a source archive for your CSS/JavaScript files.

Compressing multiple CSS/JavaScript files in just one archive will speed up your website because it will lower the transfer volume and does minimize the number of requests.

If you're using Makefiles (or anything similar) to automate building and synchronizing your website, srcar will fit in just nicely:

OBJECTS = css \
	js \
	*.html .ht* *.txt
PRODUCTION = user@host:path/to/htdocs/
OPTIONS = --recursive \
	--links \
	--update \
	--delete-after \
	--times \
	--compress

production: css js
	cd htdocs && rsync $(OPTIONS) \
		$(OBJECTS) \
		$(PRODUCTION)

css:
	srcar \
		header.css \
		article.css \
		footer.css \
		body.css

js:
	TYPE=js COMPRESSOR='java -jar compiler.jar' srcar \
		App.js \
		main.js

For CSS, there's a compressor in perl and BASH included. Find alternative implementations here:

https://github.com/markusfisch/csspack

If you want to use something different (like a CSS preprocessor), just assign the COMPRESSOR environment variable accordingly beforehand (look at the JavaScript section above).

For compressing JavaScript, you'll need to find an external compressor. The above sample does use the Google Closure Compiler:

http://code.google.com/closure/compiler/

#!/usr/bin/env bash
# Compress CSS source from stdin to stdout
compress()
{
# use perl if available or fallback to BASH string manipulation (slow!)
if which perl &>/dev/null
then
perl -e 'my $s = join( "", <STDIN> );
# remove comments
$s =~ s|/\*[^*]*\*+([^/][^*]*\*+)*/||g;
# remove newlines and white space at the beginning and at the end of lines
$s =~ s/[\t ]*[\r\n]+[\t ]*//g;
# condense tabs and blanks
$s =~ s/[\t ]+/ /g;
# remove unnecessary blanks
$s =~ s/[ ]+\{/{/g;
$s =~ s/([:\(\{,;])[ ]+/\1/g;
$s =~ s/[ ]+([\)\}])/\1/g;
print $s . "\n";'
else
local D
D=$(cat)
# remove comments
while [[ $D == */\** ]]
do
D=${D%%/\**}${D#*\*/}
done
# remove line breaks and tabs
D=${D//[$'\n'$'\r'$'\t']/}
# compress blanks and tabs
# shellcheck disable=SC2116
# shellcheck disable=SC2086
D=$(echo $D)
# remove unnecessary blanks
D=${D//: /:}
D=${D//( /(}
D=${D//\{ /\{}
D=${D// \{/\{}
D=${D// )/)}
D=${D// \}/\}}
D=${D//, /,}
D=${D//; /;}
echo "$D"
fi
}
# extension of source files and archive
readonly TYPE=${TYPE:-css}
# htdocs base directory
readonly HTDOCS=${HTDOCS:-$(H=htdocs; [ -d "$H" ] || H=; echo "${H:-.}")}
# input directory, where to find source files
readonly IN=${IN:-$HTDOCS/$TYPE/src}
# output directory, where to put the archive
readonly OUT=${OUT:-$HTDOCS/$TYPE}
# location and full name of archive
readonly ARCHIVE=${ARCHIVE:-$OUT/ar.$TYPE}
# function or script to compress the source files
readonly COMPRESSOR=${COMPRESSOR:-compress}
# additional directories to check for newer files
# WATCH
[ -d "$IN" ] || {
echo "error: input directory $IN doesn't exist"
exit 1
}
[ -d "$OUT" ] || mkdir -p "$OUT" || {
echo "error: cannot create output directory $OUT"
exit 1
}
OBJECTS=$*
# when no input files are given, simply process all files in input directory
# shellcheck disable=SC2125
[ "$OBJECTS" ] || OBJECTS=$IN/*
# create archive only if it doesn't exist or if there are newer files
# in directories to check
[ -r "$ARCHIVE" ] &&
[ -z "$(find "$WATCH${WATCH:+ }$IN/" -newer "$ARCHIVE")" ] &&
exit
for F in $OBJECTS
do
# skip directories
[ -d "$F" ] && continue
# assume input directory for objects without a slash
[[ $F != */* ]] && F=$IN/$F
cat "$F"
done | "$COMPRESSOR" > "$ARCHIVE"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment