123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- // Copyright (c) Jupyter Development Team.
- // Distributed under the terms of the Modified BSD License.
- var path = require('path');
- var findImports = require('find-imports');
- // Get the list of vendor files.
- var VENDOR_FILES = findImports('../lib/**/*.js', { flatten: true });
- var CODEMIRROR_FILES = VENDOR_FILES.filter(function(importPath) {
- return importPath.indexOf('codemirror') !== -1;
- });
- var codemirrorPaths = CODEMIRROR_FILES.map(function(importPath) {
- return importPath.replace('.js', '');
- });
- VENDOR_FILES = VENDOR_FILES.filter(function (importPath) {
- return (importPath.indexOf('codemirror') === -1 &&
- importPath.indexOf('phosphor') === -1);
- });
- /*
- Helper scripts to be used by extension authors (and extension extenders) in a
- webpack.config.json to create builds that do not include upstream extensions.
- Inspects the package.json of the user's package and those of its dependencies
- to find extensions that should be excluded.
- Slightly more than minimal valid setup in package.json:
- {
- "name": "foo-widget",
- "jupyter": {
- "lab": {
- "main": "lab-extension.js"
- }
- },
- "dependencies": {
- "jupyterlab": "*",
- "jupyter-js-widgets": "*"
- }
- }
- Example usage in webpack.config.js:
- var jlab_helpers = require('jupyterlab/scripts/extension_helpers');
- module.exports = [{
- entry: './src/lab/extension.js',
- output: {
- filename: 'lab-extension.js',
- path: '../pythonpkg/static',
- libraryTarget: 'this'
- },
- externals: jlab_helpers.upstream_externals(require)
- }];
- */
- // The "always ignore" externals used by JupyterLab, Phosphor and friends
- var BASE_EXTERNALS = [
- function(context, request, callback) {
- // All phosphor imports get mangled to use the external bundle.
- var regex = /^phosphor\/lib\/([a-z\/]+)$/;
- if(regex.test(request)) {
- var matches = regex.exec(request)[1];
- var lib = 'var phosphor.' + matches.split('/').join('.');
- return callback(null, lib);
- }
- callback();
- },
- {
- 'jupyter-js-services': 'jupyter.services',
- 'jquery': '$',
- 'jquery-ui': '$'
- }
- ];
- // Downstream extensions should exclude JupyterLab itself as well.
- var DEFAULT_EXTERNALS = BASE_EXTERNALS + [
- function(context, request, callback) {
- // JupyterLab imports get mangled to use the external bundle.
- regex = /^jupyterlab\/lib\/([a-z\/]+)$/;
- if(regex.test(request)) {
- var matches = regex.exec(request)[1];
- var lib = 'var jupyterlab.' + matches.split('/').join('.');
- return callback(null, lib);
- }
- if (codemirrorPaths.indexOf(request) !== -1) {
- return callback(null, 'var CodeMirror');
- }
- callback();
- },
- {
- 'codemirror': 'CodeMirror',
- '../lib/codemirror': 'CodeMirror',
- '../../lib/codemirror': 'CodeMirror',
- }
- ]
- // determine whether the package JSON contains a JupyterLab extension
- function validate_extension(pkg){
- try {
- // for now, just try to load the key... could check whether file exists?
- pkg['jupyter']['lab']['main']
- return true;
- } catch(err) {
- return false;
- }
- }
- // the publicly exposed function
- function upstream_externals(_require) {
- // remember which packages we have seen
- var _seen = {},
- // load the user's package.json
- _user_pkg = _require('./package.json');
- // check for whether this is the root package
- function _is_user_pkg(pkg) {
- return _user_pkg['name'] === pkg['name'];
- }
- // use the provided scoped _require and the current nested location
- // in the `node_modules` hierarchy to resolve down to the list of externals
- function _load_externals(pkg_path, pkg) {
- var pkg_externals = [pkg['name']];
- try {
- pkg_externals = pkg_externals.concat(_require(
- pkg_path + '/' + pkg['jupyter']['lab']['externals']));
- } catch (err) {
- // not really worth adding any output here... usually, just the name will
- // suffice
- }
- return pkg_externals || [];
- }
- // return an array of strings, functions or regexen that can be deferenced by
- // webpack `externals` config directive
- // https://webpack.github.io/docs/configuration.html#externals
- function _find_externals(pkg_path) {
- var pkg = _require(pkg_path + '/package.json'),
- lab_config;
- // only visit each named package once
- _seen[pkg['name']] = true;
- if (!validate_extension(pkg)) {
- if (!_is_user_pkg(pkg)) {
- return [];
- } else {
- throw Error(
- pkg['name'] + ' does not contain a jupyter configuration. ' +
- ' Please see TODO: where?'
- );
- }
- }
- console.info("Inspecting", pkg['name'],
- "for upstream JupyterLab extensions...");
- // ok, actually start building the externals. If it is the user package,
- // it SHOULDN'T be an external, as this is what the user will use for their
- // build... otherwise, load the externals, which is probably
- var externals = _is_user_pkg(pkg) ?
- DEFAULT_EXTERNALS :
- _load_externals(pkg_path, pkg, _require);
- // Recurse through the dependencies, and collect anything that has
- // a JupyterLab config
- return Object.keys(pkg['dependencies'])
- .filter(function(key){ return !_seen[key]; })
- .reduce(function(externals, dep_name){
- return externals.concat(
- _find_externals(pkg_path + '/node_modules/' + dep_name));
- }, externals);
- }
- return _find_externals(".");
- }
- module.exports = {
- upstream_externals: upstream_externals,
- validate_extension: validate_extension,
- BASE_EXTERNALS: BASE_EXTERNALS,
- CODEMIRROR_FILES: CODEMIRROR_FILES,
- VENDOR_FILES: VENDOR_FILES
- };
|