Use npm for js and less builds

This commit is contained in:
jdfreder 2015-08-11 14:06:46 -07:00 committed by Jonathan Frederic
parent ff9406f2e3
commit b88fa0163a
9 changed files with 59 additions and 228 deletions

View File

@ -14,7 +14,6 @@
"marked": "~0.3",
"MathJax": "components/MathJax#~2.5",
"moment": "~2.8.4",
"requirejs": "~2.1",
"term.js": "chjj/term.js#~0.0.4",
"text-encoding": "~0.1",
"underscore": "components/underscore#~1.5",

View File

@ -95,5 +95,5 @@ data-file-path="{{file_path}}"
{{super()}}
<script src="{{ static_url("edit/js/main.min.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("edit/js/main.bundle.js") }}" type="text/javascript" charset="utf-8"></script>
{% endblock %}

View File

@ -328,10 +328,6 @@ data-notebook-path="{{notebook_path}}"
<script src="{{ static_url("components/text-encoding/lib/encoding.js") }}" charset="utf-8"></script>
{% if ignore_minified_js %}
<script src="{{ static_url("notebook/js/main.js") }}" charset="utf-8"></script>
{% else %}
<script src="{{ static_url("notebook/js/main.min.js") }}" charset="utf-8"></script>
{% endif %}
<script src="{{ static_url("notebook/js/main.bundle.js") }}" charset="utf-8"></script>
{% endblock %}

View File

@ -16,65 +16,6 @@
{% endblock %}
<link rel="stylesheet" href="{{ base_url }}custom/custom.css" type="text/css" />
<script src="{{static_url("components/es6-promise/promise.min.js")}}" type="text/javascript" charset="utf-8"></script>
<script src="{{static_url("components/requirejs/require.js") }}" type="text/javascript" charset="utf-8"></script>
<script>
require.config({
{% if version_hash %}
urlArgs: "v={{version_hash}}",
{% endif %}
baseUrl: '{{static_url("", include_version=False)}}',
paths: {
'auth/js/main': 'auth/js/main.min',
custom : '{{ base_url }}custom',
nbextensions : '{{ base_url }}nbextensions',
widgets : '{{ base_url }}deprecatedwidgets',
kernelspecs : '{{ base_url }}kernelspecs',
underscore : 'components/underscore/underscore-min',
backbone : 'components/backbone/backbone-min',
jquery: 'components/jquery/jquery.min',
bootstrap: 'components/bootstrap/js/bootstrap.min',
bootstraptour: 'components/bootstrap-tour/build/js/bootstrap-tour.min',
jqueryui: 'components/jquery-ui/ui/minified/jquery-ui.min',
moment: 'components/moment/moment',
codemirror: 'components/codemirror',
termjs: 'components/term.js/src/term',
typeahead: 'components/jquery-typeahead/dist/jquery.typeahead'
},
shim: {
typeahead: {
deps: ["jquery"],
exports: "typeahead"
},
underscore: {
exports: '_'
},
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
bootstrap: {
deps: ["jquery"],
exports: "bootstrap"
},
bootstraptour: {
deps: ["bootstrap"],
exports: "Tour"
},
jqueryui: {
deps: ["jquery"],
exports: "$"
}
}
});
require.config({
map: {
'*':{
'contents': '{{ contents_js_source }}',
}
}
});
</script>
{% block meta %}
{% endblock %}

View File

@ -60,5 +60,5 @@ data-ws-path="{{ws_path}}"
{{super()}}
<script src="{{ static_url("terminal/js/main.min.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("terminal/js/main.bundle.js") }}" type="text/javascript" charset="utf-8"></script>
{% endblock %}

View File

@ -167,5 +167,5 @@ data-terminals-available="{{terminals_available}}"
{% block script %}
{{super()}}
<script src="{{ static_url("tree/js/main.min.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("tree/js/main.bundle.js") }}" type="text/javascript" charset="utf-8"></script>
{% endblock %}

View File

@ -9,12 +9,24 @@
"url": "https://github.com/jupyter/notebook.git"
},
"scripts": {
"bower": "bower install",
"build": "python setup.py js css"
"bower": "bower install --allow-root --config.interactive=false",
"build": "npm run build:css && npm run build:js",
"build:css": "concurrent \"npm run build:css:ipython\" \"npm run build:css:style\"",
"build:css:ipython": "lessc --source-map --include-path=./notebook/static/ ./notebook/static/style/ipython.less ./notebook/static/style/ipython.min.css",
"build:css:style": "lessc --source-map --include-path=./notebook/static/ ./notebook/static/style/style.less ./notebook/static/style/style.min.css",
"build:js": "concurrent \"npm run build:js:tree\" \"npm run build:js:terminal\" \"npm run build:js:notebook\" \"npm run build:js:edit\" \"npm run build:js:auth\"",
"build:js:notebook": "browserify notebook/static/notebook/js/main.js -o notebook/static/notebook/js/main.bundle.js",
"build:js:edit": "browserify notebook/static/edit/js/main.js -o notebook/static/edit/js/main.bundle.js",
"build:js:tree": "browserify notebook/static/tree/js/main.js -o notebook/static/tree/js/main.bundle.js",
"build:js:auth": "browserify notebook/static/auth/js/main.js -o notebook/static/auth/js/main.bundle.js",
"build:js:terminal": "browserify notebook/static/terminal/js/main.js -o notebook/static/terminal/js/main.bundle.js"
},
"devDependencies": {
"bower": "*",
"less": "~2",
"requirejs": "^2.1.17"
"browserify": "^11.0.1",
"concurrently": "^0.1.1",
"less": "~2"
}
}

View File

@ -55,7 +55,7 @@ from setupbase import (
check_package_data_first,
CompileCSS,
CompileJS,
Bower,
JSDeps,
JavascriptVersion,
css_js_prerelease,
)
@ -111,7 +111,7 @@ setup_args['cmdclass'] = {
'sdist' : css_js_prerelease(sdist, strict=True),
'css' : CompileCSS,
'js' : CompileJS,
'jsdeps' : Bower,
'jsdeps' : JSDeps,
'jsversion' : JavascriptVersion,
}

View File

@ -300,61 +300,28 @@ def run(cmd, *args, **kwargs):
return check_call(cmd, *args, **kwargs)
class Bower(Command):
class JSDeps(Command):
description = "fetch static client-side components with bower"
user_options = [
('force', 'f', "force fetching of bower dependencies"),
]
def initialize_options(self):
self.force = False
def finalize_options(self):
self.force = bool(self.force)
bower_dir = pjoin(static, 'components')
node_modules = pjoin(repo_root, 'node_modules')
def should_run(self):
if self.force:
return True
if not os.path.exists(self.bower_dir):
return True
return mtime(self.bower_dir) < mtime(pjoin(repo_root, 'bower.json'))
user_options = []
def should_run_npm(self):
if not which('npm'):
print("npm unavailable", file=sys.stderr)
return False
if not os.path.exists(self.node_modules):
return True
return mtime(self.node_modules) < mtime(pjoin(repo_root, 'package.json'))
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
if not self.should_run():
print("bower dependencies up to date")
return
if self.should_run_npm():
print("installing build dependencies with npm")
run(['npm', 'install'], cwd=repo_root)
os.utime(self.node_modules, None)
env = os.environ.copy()
env['PATH'] = npm_path
try:
run(
['bower', 'install', '--allow-root', '--config.interactive=false'],
['npm', 'install'],
cwd=repo_root,
env=env
)
except OSError as e:
print("Failed to run bower: %s" % e, file=sys.stderr)
print("You can install js dependencies with `npm install`", file=sys.stderr)
print("Failed to run `npm install`: %s" % e, file=sys.stderr)
raise
os.utime(self.bower_dir, None)
# update package data in case this created new files
update_package_data(self.distribution)
@ -374,103 +341,51 @@ class CompileCSS(Command):
def finalize_options(self):
pass
sources = []
targets = []
for name in ('ipython', 'style'):
sources.append(pjoin(static, 'style', '%s.less' % name))
targets.append(pjoin(static, 'style', '%s.min.css' % name))
def run(self):
self.run_command('jsdeps')
env = os.environ.copy()
env['PATH'] = npm_path
for src, dst in zip(self.sources, self.targets):
try:
run(['lessc',
'--source-map',
'--include-path=%s' % pipes.quote(static),
src,
dst,
], cwd=repo_root, env=env)
except OSError as e:
print("Failed to build css: %s" % e, file=sys.stderr)
print("You can install js dependencies with `npm install`", file=sys.stderr)
raise
try:
run(
['npm', 'run', 'build:css'],
cwd=repo_root,
env=env
)
except OSError as e:
print("Failed to run `npm run build:css`: %s" % e, file=sys.stderr)
raise
# update package data in case this created new files
update_package_data(self.distribution)
class CompileJS(Command):
"""Rebuild Notebook Javascript main.min.js files
Calls require via build-main.js
"""
description = "Rebuild Notebook Javascript main.min.js files"
user_options = [
('force', 'f', "force rebuilding js targets"),
]
user_options = []
def initialize_options(self):
self.force = False
pass
def finalize_options(self):
self.force = bool(self.force)
apps = ['notebook', 'tree', 'edit', 'terminal', 'auth']
targets = [ pjoin(static, app, 'js', 'main.min.js') for app in apps ]
pass
def sources(self, name):
"""Generator yielding .js sources that an application depends on"""
yield pjoin(static, name, 'js', 'main.js')
for sec in [name, 'base', 'auth']:
for f in glob(pjoin(static, sec, 'js', '*.js')):
if not f.endswith('.min.js'):
yield f
yield pjoin(static, 'services', 'config.js')
if name == 'notebook':
for f in glob(pjoin(static, 'services', '*', '*.js')):
yield f
for parent, dirs, files in os.walk(pjoin(static, 'components')):
if os.path.basename(parent) == 'MathJax':
# don't look in MathJax, since it takes forever to walk it
dirs[:] = []
continue
for f in files:
yield pjoin(parent, f)
def should_run(self, name, target):
if self.force or not os.path.exists(target):
return True
target_mtime = mtime(target)
for source in self.sources(name):
if mtime(source) > target_mtime:
print(source, target)
return True
return False
def build_main(self, name):
"""Build main.min.js"""
target = pjoin(static, name, 'js', 'main.min.js')
if not self.should_run(name, target):
log.info("%s up to date" % target)
return
log.info("Rebuilding %s" % target)
run(['node', 'tools/build-main.js', name])
def run(self):
self.run_command('jsdeps')
env = os.environ.copy()
env['PATH'] = npm_path
pool = ThreadPool()
pool.map(self.build_main, self.apps)
try:
run(
['npm', 'run', 'build:js'],
cwd=repo_root,
env=env
)
except OSError as e:
print("Failed to run `npm run build:js`: %s" % e, file=sys.stderr)
raise
# update package data in case this created new files
update_package_data(self.distribution)
class JavascriptVersion(Command):
"""write the javascript version to notebook javascript"""
description = "Write Jupyter version to javascript"
@ -502,45 +417,13 @@ def css_js_prerelease(command, strict=False):
class DecoratedCommand(command):
def run(self):
self.distribution.run_command('jsversion')
jsdeps = self.distribution.get_command_obj('jsdeps')
js = self.distribution.get_command_obj('js')
css = self.distribution.get_command_obj('css')
jsdeps.force = js.force = strict
targets = [ jsdeps.bower_dir ]
targets.extend(js.targets)
targets.extend(css.targets)
missing = [ t for t in targets if not os.path.exists(t) ]
if not is_repo and not missing:
# If we're an sdist, we aren't a repo and everything should be present.
# Don't rebuild js/css in that case.
command.run(self)
return
try:
self.distribution.run_command('css')
self.distribution.run_command('jsdeps')
self.distribution.run_command('js')
self.distribution.run_command('css')
except Exception as e:
# refresh missing
missing = [ t for t in targets if not os.path.exists(t) ]
if strict or missing:
# die if strict or any targets didn't build
prefix = os.path.commonprefix([repo_root + os.sep] + missing)
missing = [ m[len(prefix):] for m in missing ]
log.warn("rebuilding js and css failed. The following required files are missing: %s" % missing)
raise e
else:
log.warn("rebuilding js and css failed (not a problem)")
log.warn(str(e))
# check again for missing targets, just in case:
missing = [ t for t in targets if not os.path.exists(t) ]
if missing:
# command succeeded, but targets still missing (?!)
prefix = os.path.commonprefix([repo_root + os.sep] + missing)
missing = [ m[len(prefix):] for m in missing ]
raise ValueError("The following required files are missing: %s" % missing)
log.warn("rebuilding js and css failed.)
raise e
command.run(self)
return DecoratedCommand