Merge pull request #6196 from minrk/git-friendlyish-less-css

Make less/sourcemaps a bit friendlier to git
This commit is contained in:
Min RK 2014-07-24 12:09:54 -07:00
commit 43e25ab4d9
9 changed files with 11662 additions and 29 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ docs/source/api/generated
docs/source/config/options
docs/gh-pages
IPython/html/notebook/static/mathjax
IPython/html/static/style/*.map
*.py[co]
__pycache__
*.egg-info

View File

@ -8,13 +8,48 @@ from subprocess import check_output
pjoin = os.path.join
static_dir = 'static'
components_dir = os.path.join(static_dir, 'components')
components_dir = pjoin(static_dir, 'components')
here = os.path.dirname(__file__)
min_less_version = '1.7.0'
max_less_version = '1.8.0' # exclusive
def css(minify=True, verbose=False):
def _need_css_update():
"""Does less need to run?"""
static_path = pjoin(here, static_dir)
css_targets = [
pjoin(static_path, 'style', '%s.min.css' % name)
for name in ('style', 'ipython')
]
css_maps = [t + '.map' for t in css_targets]
targets = css_targets + css_maps
if not all(os.path.exists(t) for t in targets):
# some generated files don't exist
return True
earliest_target = sorted(os.stat(t).st_mtime for t in targets)[0]
# check if any .less files are newer than the generated targets
for (dirpath, dirnames, filenames) in os.walk(static_path):
for f in filenames:
if f.endswith('.less'):
path = pjoin(static_path, dirpath, f)
timestamp = os.stat(path).st_mtime
if timestamp > earliest_target:
return True
return False
def css(minify=False, verbose=False, force=False):
"""generate the css from less files"""
minify = _to_bool(minify)
verbose = _to_bool(verbose)
force = _to_bool(force)
# minify implies force because it's not the default behavior
if not force and not minify and not _need_css_update():
print("css up-to-date")
return
for name in ('style', 'ipython'):
source = pjoin('style', "%s.less" % name)
target = pjoin('style', "%s.min.css" % name)
@ -28,8 +63,6 @@ def _to_bool(b):
def _compile_less(source, target, sourcemap, minify=True, verbose=False):
"""Compile a less file by source and target relative to static_dir"""
minify = _to_bool(minify)
verbose = _to_bool(verbose)
min_flag = '-x' if minify is True else ''
ver_flag = '--verbose' if verbose is True else ''
@ -46,7 +79,7 @@ def _compile_less(source, target, sourcemap, minify=True, verbose=False):
if V(less_version) >= V(max_less_version):
raise ValueError("lessc too new: %s >= %s. Use `$ npm install lesscss@X.Y.Z` to install a specific version of less" % (less_version, max_less_version))
static_path = pjoin(os.getcwd(), static_dir)
static_path = pjoin(here, static_dir)
with lcd(static_dir):
local('lessc {min_flag} {ver_flag} --source-map={sourcemap} --source-map-basepath={static_path} --source-map-rootpath="../" {source} {target}'.format(**locals()))

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,7 @@ git hooks for IPython
add these to your `.git/hooks`
For now, we just have `post-checkout` and `post-merge`,
both of which just update submodules,
both of which update submodules and attempt to rebuild css sourcemaps,
so make sure that you have a fully synced repo whenever you checkout or pull.
To use these hooks, run `./install-hooks.sh`.

View File

@ -2,3 +2,16 @@
git submodule init
git submodule update
PREVIOUS_HEAD=$1
# if style changed (and less/fabric available), rebuild sourcemaps
if [[
! -z "$(git diff $PREVIOUS_HEAD IPython/html/static/style/ipython.min.css)"
&& ! -z "$(git diff $PREVIOUS_HEAD IPython/html/static/style/style.min.css)"
&& ! -z $(which 2>/dev/null lessc)
&& ! -z $(which 2>/dev/null fab)
]]; then
echo "rebuilding sourcemaps"
cd IPython/html
fab css
fi

View File

@ -1,4 +0,0 @@
#!/bin/sh
git submodule init
git submodule update

1
git-hooks/post-merge Symbolic link
View File

@ -0,0 +1 @@
post-checkout

View File

@ -72,6 +72,7 @@ from setupbase import (
get_bdist_wheel,
CompileCSS,
JavascriptVersion,
css_js_prerelease,
install_symlinked,
install_lib_symlink,
install_scripts_for_symlink,
@ -227,8 +228,10 @@ class UploadWindowsInstallers(upload):
self.upload_file('bdist_wininst', 'any', dist_file)
setup_args['cmdclass'] = {
'build_py': check_package_data_first(git_prebuild('IPython')),
'sdist' : git_prebuild('IPython', sdist),
'build_py': css_js_prerelease(
check_package_data_first(git_prebuild('IPython')),
strict=False),
'sdist' : css_js_prerelease(git_prebuild('IPython', sdist)),
'upload_wininst' : UploadWindowsInstallers,
'submodule' : UpdateSubmodules,
'css' : CompileCSS,
@ -302,7 +305,7 @@ if 'setuptools' in sys.modules:
# setup.py develop should check for submodules
from setuptools.command.develop import develop
setup_args['cmdclass']['develop'] = require_submodules(develop)
setup_args['cmdclass']['bdist_wheel'] = get_bdist_wheel()
setup_args['cmdclass']['bdist_wheel'] = css_js_prerelease(get_bdist_wheel())
setuptools_extra_args['zip_safe'] = False
setuptools_extra_args['entry_points'] = {'console_scripts':find_entry_points()}

View File

@ -18,6 +18,7 @@ import errno
import os
import sys
from distutils import log
from distutils.command.build_py import build_py
from distutils.command.build_scripts import build_scripts
from distutils.command.install import install
@ -25,7 +26,7 @@ from distutils.command.install_scripts import install_scripts
from distutils.cmd import Command
from fnmatch import fnmatch
from glob import glob
from subprocess import call
from subprocess import check_call
from setupext import install_data_ext
@ -666,16 +667,26 @@ class CompileCSS(Command):
Requires various dev dependencies, such as fabric and lessc.
"""
description = "Recompile Notebook CSS"
user_options = []
user_options = [
('minify', 'x', "minify CSS"),
('force', 'f', "force recompilation of CSS"),
]
def initialize_options(self):
pass
self.minify = False
self.force = False
def finalize_options(self):
pass
self.minify = bool(self.minify)
self.force = bool(self.force)
def run(self):
call("fab css", shell=True, cwd=pjoin(repo_root, "IPython", "html"))
check_call([
"fab",
"css:minify=%s,force=%s" % (self.minify, self.force),
], cwd=pjoin(repo_root, "IPython", "html"),
)
class JavascriptVersion(Command):
"""write the javascript version to notebook javascript"""
@ -697,4 +708,21 @@ class JavascriptVersion(Command):
if line.startswith("IPython.version"):
line = 'IPython.version = "{0}";\n'.format(version)
f.write(line)
def css_js_prerelease(command, strict=True):
"""decorator for building js/minified css prior to a release"""
class DecoratedCommand(command):
def run(self):
self.distribution.run_command('jsversion')
css = self.distribution.get_command_obj('css')
css.minify = True
try:
self.distribution.run_command('css')
except Exception as e:
if strict:
raise
else:
log.warn("Failed to build css sourcemaps: %s" % e)
command.run(self)
return DecoratedCommand