doit overhaul
most notably now we preserve the mtime of the source files so cachebusted static urls won't change every time everything is regenerated for whatever reason
This commit is contained in:
parent
092cc1919d
commit
6d8991ee65
93
dodo.py
93
dodo.py
|
@ -1,3 +1,10 @@
|
||||||
|
from doit import create_after
|
||||||
|
|
||||||
|
def reltouch(source_filename, dest_filename):
|
||||||
|
from os import stat, utime
|
||||||
|
stat_res = stat(source_filename)
|
||||||
|
utime(dest_filename, ns=(stat_res.st_atime_ns, stat_res.st_mtime_ns))
|
||||||
|
|
||||||
def resize_image(basename, width, format):
|
def resize_image(basename, width, format):
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
with Image.open('assets/{}.png'.format(basename)) as im:
|
with Image.open('assets/{}.png'.format(basename)) as im:
|
||||||
|
@ -22,9 +29,10 @@ def resize_image(basename, width, format):
|
||||||
optimize = True,
|
optimize = True,
|
||||||
)
|
)
|
||||||
new.save('static/{}-{}.{}'.format(basename, width, format), **kwargs)
|
new.save('static/{}-{}.{}'.format(basename, width, format), **kwargs)
|
||||||
|
reltouch('assets/{}.png'.format(basename), 'static/{}-{}.{}'.format(basename, width, format))
|
||||||
|
|
||||||
def task_gen_logo():
|
def task_logotype():
|
||||||
"""generate versions of the logo in various sizes"""
|
"""resize and convert logotype"""
|
||||||
widths = (200, 400, 600, 800)
|
widths = (200, 400, 600, 800)
|
||||||
formats = ('jpeg', 'webp')
|
formats = ('jpeg', 'webp')
|
||||||
for width in widths:
|
for width in widths:
|
||||||
|
@ -37,7 +45,8 @@ def task_gen_logo():
|
||||||
clean=True,
|
clean=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def task_button_icons():
|
def task_service_icon():
|
||||||
|
"""resize and convert service icons"""
|
||||||
widths = (20,40,80)
|
widths = (20,40,80)
|
||||||
formats = ('webp', 'png')
|
formats = ('webp', 'png')
|
||||||
for width in widths:
|
for width in widths:
|
||||||
|
@ -51,20 +60,29 @@ def task_button_icons():
|
||||||
clean=True,
|
clean=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def task_copy_asset():
|
def task_copy():
|
||||||
import shutil
|
"copy assets verbatim"
|
||||||
|
|
||||||
assets = ('icon.png', 'logotype.png', 'settings.js')
|
assets = ('icon.png', 'logotype.png', 'settings.js')
|
||||||
|
|
||||||
|
def do_the_thing(src, dst):
|
||||||
|
from shutil import copy
|
||||||
|
copy(src, dst)
|
||||||
|
reltouch(src, dst)
|
||||||
|
|
||||||
for asset in assets:
|
for asset in assets:
|
||||||
|
src = 'assets/{}'.format(asset)
|
||||||
|
dst = 'static/{}'.format(asset)
|
||||||
yield dict(
|
yield dict(
|
||||||
name=asset,
|
name=asset,
|
||||||
actions=[(lambda asset: shutil.copy(f'assets/{asset}', f'static/{asset}'), (asset,))],
|
actions=[(do_the_thing, (src, dst))],
|
||||||
targets=[f'static/{asset}'],
|
targets=[src],
|
||||||
file_dep=[f'assets/{asset}'],
|
file_dep=[dst],
|
||||||
clean=True,
|
clean=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def task_minify_css():
|
def task_minify_css():
|
||||||
"""minify css"""
|
"""minify css file with csscompressor"""
|
||||||
|
|
||||||
from csscompressor import compress
|
from csscompressor import compress
|
||||||
|
|
||||||
|
@ -72,6 +90,7 @@ def task_minify_css():
|
||||||
with open('assets/styles.css') as in_:
|
with open('assets/styles.css') as in_:
|
||||||
with open('static/styles.css', 'w') as out:
|
with open('static/styles.css', 'w') as out:
|
||||||
out.write(compress(in_.read()))
|
out.write(compress(in_.read()))
|
||||||
|
reltouch('assets/styles.css', 'static/styles.css')
|
||||||
|
|
||||||
return dict(
|
return dict(
|
||||||
actions=[minify],
|
actions=[minify],
|
||||||
|
@ -80,48 +99,50 @@ def task_minify_css():
|
||||||
clean=True,
|
clean=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@create_after('logotype')
|
||||||
|
@create_after('service_icon')
|
||||||
|
@create_after('copy')
|
||||||
|
@create_after('minify_css')
|
||||||
|
def task_compress():
|
||||||
|
"make gzip and brotli compressed versions of each static file for the server to lazily serve"
|
||||||
|
from glob import glob
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
def cross(a, b):
|
files = chain(
|
||||||
for A in a:
|
glob('static/*.css'),
|
||||||
for B in b:
|
glob('static/*.js'),
|
||||||
yield (A, B)
|
glob('static/*.jpeg'),
|
||||||
|
glob('static/*.png'),
|
||||||
|
glob('static/*.webp'),
|
||||||
|
)
|
||||||
|
|
||||||
def task_compress_static():
|
def compress_brotli(filename):
|
||||||
import brotli
|
import brotli
|
||||||
import gzip
|
with open(filename, 'rb') as in_:
|
||||||
|
with open(filename + '.br', 'wb') as out:
|
||||||
|
out.write(brotli.compress(in_.read()))
|
||||||
|
reltouch(filename, filename+'.br')
|
||||||
|
|
||||||
files = (
|
def compress_gzip(filename):
|
||||||
'static/styles.css',
|
import gzip
|
||||||
'static/icon.png',
|
with open(filename, 'rb') as in_:
|
||||||
'static/logotype.png',
|
with gzip.open(filename + '.gz', 'wb') as out:
|
||||||
'static/settings.js',
|
out.write(in_.read())
|
||||||
) + tuple((f'static/logotype-{width}.{format}' for width, format in cross((200, 400, 600, 800), ('jpeg','webp'))))
|
reltouch(filename, filename+'.gz')
|
||||||
|
|
||||||
|
|
||||||
def compress_brotli(dependencies):
|
|
||||||
for filename in dependencies:
|
|
||||||
with open(filename, 'rb') as in_:
|
|
||||||
with open(filename + '.br', 'wb') as out:
|
|
||||||
out.write(brotli.compress(in_.read()))
|
|
||||||
def compress_gzip(dependencies):
|
|
||||||
for filename in dependencies:
|
|
||||||
with open(filename, 'rb') as in_:
|
|
||||||
with gzip.open(filename + '.gz', 'wb') as out:
|
|
||||||
out.write(in_.read())
|
|
||||||
|
|
||||||
for filename in files:
|
for filename in files:
|
||||||
yield dict(
|
yield dict(
|
||||||
file_dep=(filename,),
|
file_dep=(filename,),
|
||||||
targets=(filename+'.br',),
|
targets=(filename+'.br',),
|
||||||
name=filename+'.br',
|
name=filename+'.br',
|
||||||
actions=[compress_brotli],
|
actions=[(compress_brotli, (filename,))],
|
||||||
clean=True,
|
clean=True,
|
||||||
)
|
)
|
||||||
yield dict(
|
yield dict(
|
||||||
file_dep=(filename,),
|
file_dep=(filename,),
|
||||||
targets=(filename+'.gz',),
|
targets=(filename+'.gz',),
|
||||||
name=filename+'.gz',
|
name=filename+'.gz',
|
||||||
actions=[compress_gzip],
|
actions=[(compress_gzip, (filename,))],
|
||||||
clean=True,
|
clean=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue