diff options
author | Luke Shumaker <LukeShu@sbcglobal.net> | 2013-07-14 15:04:01 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@parabola.nu> | 2018-01-15 21:37:30 -0500 |
commit | 5a29ccbc78b8a222c16840ae067ce64f60507539 (patch) | |
tree | cd821c326e6c1cc51dc5013b7ea2c79eefe60174 | |
parent | 72ddf3b134a21896f40c94e8a9c7173f4274b7fe (diff) |
Add a Makefile to download 3rd-party assets, and generate derived files
The goal is to generate the *exact* files that are already in git. This
is important, because it lets us verify that minified files that are
checked in truly are created from the sources that they claim to be.
Reproducible builds, yo.
I ran `make clean && make && git add .` before committing this. And none
of the files changed!
Long-term, it might be better to build this into the normal Django
staticfiles pipeline. But for now, I wanted to be able to identify
exactly how everything was created, as it is now.
-rw-r--r-- | Makefile | 161 | ||||
-rw-r--r-- | Makefile.d/bootstrap-typeahead.js.patch | 38 | ||||
-rw-r--r-- | Makefile.d/homepage.js.in | 36 | ||||
-rw-r--r-- | Makefile.d/jquery-1.8.3.min.js.preamble | 1 | ||||
-rw-r--r-- | Makefile.d/jquery.tablesorter-2.7.min.js.preamble | 4 | ||||
-rw-r--r-- | Makefile.d/konami.js.patch | 46 |
6 files changed, 286 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..1a077637 --- /dev/null +++ b/Makefile @@ -0,0 +1,161 @@ +# The idea here is to be able to re-generate the exact Javascript +# files as they exist in git. This means munging whitespace in weird +# ways, using specific versions of various JS minimizers... + +# Dependencies: +# - bsdtar +# - coreutils +# - gitget <https://git.parabola.nu/packages/libretools.git/tree/src/gitget/gitget> +# - java (for closure-compiler) +# - node (for UglifyJS 1) +# - npm (for UglifyJS 2) +# - patch +# - perl +# - pngcrush +# - sed +# - wget + +# Where are we? +dl-cache = ../download-cache +www = $(dl-cache)/www +bin = $(dl-cache)/bin + +# What versions of 3rd party libraries are we using? +jquery-ver=1.8.3 +bootstrap-ver=2.1.1 +tablesorter-ver=2.7 +d3-ver=3.0.6 +konami-ver=c0f686e647765860ff4d2fcb7b48122785432b75 + +targets = \ + sitestatic/rss.png \ + sitestatic/rss@2x.png \ + sitestatic/bootstrap-typeahead.js \ + sitestatic/homepage.js \ + sitestatic/jquery-$(jquery-ver).min.js \ + sitestatic/jquery.tablesorter-$(tablesorter-ver).js \ + sitestatic/jquery.tablesorter-$(tablesorter-ver).min.js \ + sitestatic/konami.min.js \ + visualize/static/d3-$(d3-ver).js \ + visualize/static/d3-$(d3-ver).min.js \ + retro/static/2013/bootstrap-typeahead.min.1aacd3d7f4db.js \ + retro/static/2013/konami.min.e165c814457d.js + + +# The base rules + +all: $(targets) +.PHONY: all + +js-basenames = $(sort $(patsubst %.min,%,$(patsubst %.js,%,$(filter %.js,$(targets))))) +generated = $(sort $(targets) $(foreach f,$(js-basenames),$f.js $f.min.js)) +clean: + rm -f -- $(generated) +.PHONY: clean + +# Make directories +$(dl-cache) $(bin): + mkdir -p '$@' + +# Don't have non-minimized .js stick around unless we asked for them. +.INTERMEDIATE: $(filter-out $(targets),$(generated)) + +# Turn on sane error handling +.DELETE_ON_ERROR: + + +# How to download files + + mangle = $(subst %,^25,$(subst :,^3A,$(subst =,^3D,$(subst ^,^5E,$1)))) +unmangle = $(subst ^5E,^,$(subst ^3D,=,$(subst ^3A,:,$(subst ^25,%,$1)))) + +$(www)/http/%: + mkdir -p '$(@D)' + wget 'http://$(call unmangle,$*)' -O '$@' + test -f '$@' && touch '$@' + +$(www)/https/%: + mkdir -p '$(@D)' + wget 'https://$(call unmangle,$*)' -O '$@' + test -f '$@' && touch '$@' + +$(www)/git/%: + mkdir -p '$(@D)' + gitget checkout 'git://$(call unmangle,$*)' '$@' || { rm -rf -- '$@'; false; } + test -d '$@' && touch '$@' || { rm -rf -- '$@'; false; } + + +# How to install any of the minifiers in use + +# Any of the UglifyJS 1.3.x releases will produce the same output for these inputs +$(bin)/uglifyjs-1.3: $(www)/git/github.com/mishoo/UglifyJS.git\#tag=v1.3.5 | $(bin) + printf '%s\n' '#!/bin/sh' 'exec $</bin/uglifyjs --no-copyright --ascii --max-line-len 0 "$$@"' | install -m755 /dev/stdin '$@' + +# Any of the UglifyJS 2.2.x releases will produce the same output for these inputs +$(dl-cache)/uglifyjs-2.2: $(www)/git/github.com/mishoo/UglifyJS2.git\#tag=v2.2.5 | $(dl-cache) + cp -r $< $@ || { rm -rf -- '$@'; false; } + cd $@ && npm install || { rm -rf -- '$@'; false; } +$(bin)/uglifyjs-2.2: $(dl-cache)/uglifyjs-2.2 | $(bin) + printf '%s\n' '#!/bin/sh' 'exec $</bin/uglifyjs --mangle --compress -- "$$@"' | install -m755 /dev/stdin '$@' + +# Closure compiler 20121212 produces the same output +$(dl-cache)/unzip/compiler-20121212/%: $(www)/https/web.archive.org/web/20151226141014/https^3A//closure-compiler.googlecode.com/files/compiler-20121212.tar.gz + mkdir -p '$(@D)' + bsdtar xfO '$<' '$*' > '$@' +$(bin)/closure-compiler: $(dl-cache)/unzip/compiler-20121212/compiler.jar | $(bin) + printf '%s\n' '#!/bin/sh' 'exec java -jar $< "$$@"' | install -m755 /dev/stdin '$@' + + +# The meat of the Makefile + +# Downloaded images +$(dl-cache)/unzip/Feedicons_v.2/%: $(www)/https/web.archive.org/web/20120514074507/http^3A//www.zeusboxstudio.com/file_download/1/Feedicons_v.2.zip + mkdir -p '$(@D)' + bsdtar xfO $< 'Feedicons v.2/$*' > '$@' +sitestatic/rss.png: $(dl-cache)/unzip/Feedicons_v.2/RSS_16.png + cp $< $@ +sitestatic/rss@2x.png: $(dl-cache)/unzip/Feedicons_v.2/RSS_32.png + pngcrush $< $@ + +# Non-minified JavaScript +sitestatic/bootstrap-typeahead.js: sitestatic/%: $(www)/https/raw.github.com/twitter/bootstrap/v$(bootstrap-ver)/js/% Makefile.d/%.patch + cp $< $@ + patch -i Makefile.d/$*.patch $@ +sitestatic/jquery-$(jquery-ver).js: sitestatic/%: $(www)/http/code.jquery.com/% + cp $< $@ +sitestatic/jquery.tablesorter-$(tablesorter-ver).js: $(www)/https/raw.github.com/Mottie/tablesorter/v$(tablesorter-ver)/js/jquery.tablesorter.js + cp $< $@ +sitestatic/konami.js: sitestatic/%: $(www)/https/raw.github.com/snaptortoise/konami-js/$(konami-ver)/% Makefile.d/%.patch + cp $< $@ + patch -i Makefile.d/$*.patch $@ +visualize/static/d3-$(d3-ver).js: %: $(www)/https/raw.github.com/mbostock/d3/v$(d3-ver)/d3.js + cp $< $@ + +# JavaScript minification +sitestatic/bootstrap-typeahead.min.js: %.min.js: $(bin)/uglifyjs-1.3 %.js + $^ > $@ +sitestatic/jquery-$(jquery-ver).min.js: sitestatic/%.min.js: sitestatic/%.js Makefile.d/%.min.js.preamble + { cat Makefile.d/$*.min.js.preamble && $(bin)/uglifyjs-1.3 $<; } > $@ +sitestatic/jquery.tablesorter-$(tablesorter-ver).min.js: sitestatic/%.min.js: sitestatic/%.js Makefile.d/%.min.js.preamble $(bin)/closure-compiler + @# The tr/sed is to turn all of the newlines except for the last one into spaces + { cat Makefile.d/$*.min.js.preamble && $(bin)/closure-compiler $< | tr '\n' ' ' | sed 's, $$,\n,'; } > $@ +sitestatic/konami.min.js: %.min.js: $(bin)/uglifyjs-2.2 %.js + @# The sed is to insert newlines and whitespace at the correct places; presumably to match Dan copy/pasting into an editor. + $^ | sed -r -e 's:e\.iphone\.stop_x|s=this\.tap===:\n\t&:g' -e 's,return"string",\n&,' | sed -e 's,;$$,,' -e '$$s,$$,\n,' > $@ +visualize/static/d3-$(d3-ver).min.js: %.min.js: $(bin)/uglifyjs-2.2 %.js + $^ > $@ + +# Files that make use of that minified JavaScript +retro/static/2013/konami.min.e165c814457d.js: sitestatic/konami.min.js + cp $< $@ +retro/static/2013/bootstrap-typeahead.min.1aacd3d7f4db.js: sitestatic/bootstrap-typeahead.min.js + @# Trim trailing semicolon and newline + < $< sed 's/;$$//' | perl -pe 'chomp if eof' > $@ +sitestatic/homepage.js: sitestatic/bootstrap-typeahead.min.js sitestatic/konami.min.js Makefile.d/homepage.js.in + { \ + cat sitestatic/bootstrap-typeahead.min.js && \ + echo && \ + sed -e 's,^\s*,,' -e 's,^return.*,&;,' sitestatic/konami.min.js && \ + echo && \ + cat Makefile.d/homepage.js.in ; \ + } > $@ diff --git a/Makefile.d/bootstrap-typeahead.js.patch b/Makefile.d/bootstrap-typeahead.js.patch new file mode 100644 index 00000000..dfbab80b --- /dev/null +++ b/Makefile.d/bootstrap-typeahead.js.patch @@ -0,0 +1,38 @@ +commit f3e23371fa0473c82c28932e85570d94e5fc232a +Author: Dan McGee <dan@archlinux.org> +Date: Mon Sep 24 20:21:15 2012 -0500 + + Don't auto-select the first item in typeahead + + This assumption was baked into the Twitter bootstrap JS; kill it so it + is still easy to do a freeform search if wanted. + + Signed-off-by: Dan McGee <dan@archlinux.org> + +diff --git a/sitestatic/bootstrap-typeahead.js b/sitestatic/bootstrap-typeahead.js +index c2ccdea..3d355ae 100644 +--- a/sitestatic/bootstrap-typeahead.js ++++ b/sitestatic/bootstrap-typeahead.js +@@ -45,9 +45,11 @@ + + , select: function () { + var val = this.$menu.find('.active').attr('data-value') +- this.$element +- .val(this.updater(val)) +- .change() ++ if (val) { ++ this.$element ++ .val(this.updater(val)) ++ .change() ++ } + return this.hide() + } + +@@ -141,7 +143,6 @@ + return i[0] + }) + +- items.first().addClass('active') + this.$menu.html(items) + return this + } diff --git a/Makefile.d/homepage.js.in b/Makefile.d/homepage.js.in new file mode 100644 index 00000000..2d6f7910 --- /dev/null +++ b/Makefile.d/homepage.js.in @@ -0,0 +1,36 @@ +function setupTypeahead() { + $('#pkgsearch-field').typeahead({ + source: function(query, callback) { + $.getJSON('/opensearch/packages/suggest', {q: query}, function(data) { + callback(data[1]); + }); + }, + matcher: function(item) { return true; }, + sorter: function(items) { return items; }, + menu: '<ul class="pkgsearch-typeahead"></ul>', + items: 10, + updater: function(item) { + $('#pkgsearch-field').val(item); + $('#pkgsearch-form').submit(); + return item; + } + }).attr('autocomplete', 'off'); + $('#pkgsearch-field').keyup(function(e) { + if (e.keyCode === 13 && + $('ul.pkgsearch-typeahead li.active').size() === 0) { + $('#pkgsearch-form').submit(); + } + }); +} + +function setupKonami(image_src) { + var konami = new Konami(function() { + $('#konami').html('<img src="' + image_src + '" alt=""/>'); + setTimeout(function() { + $('#konami').fadeIn(500); + }, 500); + $('#konami').click(function() { + $('#konami').fadeOut(500); + }); + }); +} diff --git a/Makefile.d/jquery-1.8.3.min.js.preamble b/Makefile.d/jquery-1.8.3.min.js.preamble new file mode 100644 index 00000000..ae08a973 --- /dev/null +++ b/Makefile.d/jquery-1.8.3.min.js.preamble @@ -0,0 +1 @@ +/*! jQuery v1.8.3 jquery.com | jquery.org/license */
diff --git a/Makefile.d/jquery.tablesorter-2.7.min.js.preamble b/Makefile.d/jquery.tablesorter-2.7.min.js.preamble new file mode 100644 index 00000000..a6e11689 --- /dev/null +++ b/Makefile.d/jquery.tablesorter-2.7.min.js.preamble @@ -0,0 +1,4 @@ +/*! +* TableSorter 2.7 min - Client-side table sorting with ease! +* Copyright (c) 2007 Christian Bach +*/ diff --git a/Makefile.d/konami.js.patch b/Makefile.d/konami.js.patch new file mode 100644 index 00000000..f6df91c4 --- /dev/null +++ b/Makefile.d/konami.js.patch @@ -0,0 +1,46 @@ +--- ..//web-cache/www/https/raw.github.com/snaptortoise/konami-js/c0f686e647765860ff4d2fcb7b48122785432b75/konami.js 2015-04-14 17:46:09.372597458 -0400 ++++ sitestatic/konami.js 2015-04-14 22:39:28.549281737 -0400 +@@ -56,7 +56,7 @@ + load: function(link){ + this.orig_keys = this.keys; + konami.addEvent(document,"touchmove",function(e){ +- if(e.touches.length == 1 && konami.iphone.capture==true){ ++ if(e.touches.length == 1 && konami.iphone.capture===true){ + var touch = e.touches[0]; + konami.iphone.stop_x = touch.pageX; + konami.iphone.stop_y = touch.pageY; +@@ -66,7 +66,7 @@ + } + }); + konami.addEvent(document,"touchend",function(evt){ +- if (konami.iphone.tap==true) konami.iphone.check_direction(link); ++ if (konami.iphone.tap===true) konami.iphone.check_direction(link); + },false); + konami.addEvent(document,"touchstart", function(evt){ + konami.iphone.start_x = evt.changedTouches[0].pageX +@@ -76,12 +76,12 @@ + }); + }, + check_direction: function(link){ +- x_magnitude = Math.abs(this.start_x-this.stop_x) +- y_magnitude = Math.abs(this.start_y-this.stop_y) +- x = ((this.start_x-this.stop_x) < 0) ? "RIGHT" : "LEFT"; +- y = ((this.start_y-this.stop_y) < 0) ? "DOWN" : "UP"; +- result = (x_magnitude > y_magnitude) ? x : y; +- result = (this.tap==true) ? "TAP" : result; ++ var x_magnitude = Math.abs(this.start_x-this.stop_x) ++ var y_magnitude = Math.abs(this.start_y-this.stop_y) ++ var x = ((this.start_x-this.stop_x) < 0) ? "RIGHT" : "LEFT"; ++ var y = ((this.start_y-this.stop_y) < 0) ? "DOWN" : "UP"; ++ var result = (x_magnitude > y_magnitude) ? x : y; ++ result = (this.tap===true) ? "TAP" : result; + + if (result==this.keys[0]) this.keys = this.keys.slice(1,this.keys.length) + if (this.keys.length==0) { +@@ -99,4 +99,4 @@ + } + + return konami; +-} +\ No newline at end of file ++} |