diff --git a/build/webpack/common.js b/build/webpack/common.js index 58e0845dfeac..d6e620e73e4c 100644 --- a/build/webpack/common.js +++ b/build/webpack/common.js @@ -27,6 +27,11 @@ exports.nodeModulesToExternalize = [ 'node-stream-zip', 'xml2js', 'vsls/vscode', + 'pdfkit', + 'crypto-js', + 'fontkit', + 'linebreak', + 'png-js' ]; exports.nodeModulesToReplacePaths = [ ...exports.nodeModulesToExternalize diff --git a/build/webpack/common.ts b/build/webpack/common.ts index 16ddebb2e869..de762dc824e6 100644 --- a/build/webpack/common.ts +++ b/build/webpack/common.ts @@ -29,11 +29,16 @@ export const nodeModulesToExternalize = [ 'node-stream-zip', 'xml2js', 'vsls/vscode', + 'pdfkit', + 'crypto-js', + 'fontkit', + 'linebreak', + 'png-js' ]; export const nodeModulesToReplacePaths = [ ...nodeModulesToExternalize -] +]; export function getDefaultPlugins(name: 'extension' | 'debugger' | 'dependencies' | 'datascience-ui') { const plugins = []; diff --git a/build/webpack/pdfkit.js b/build/webpack/pdfkit.js new file mode 100644 index 000000000000..5c31590a3924 --- /dev/null +++ b/build/webpack/pdfkit.js @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +'use strict'; + +/* +This file is only used when using webpack for bundling. +We have a dummy file so that webpack doesn't fall over when trying to bundle pdfkit. +Just point it to a dummy file (this file). +Once webpack is done, we override the pdfkit.js file in the externalized node modules directory +with the actual source of pdfkit that needs to be used by nodejs (our extension code). +*/ + +class PDFDocument {} +module.exports = PDFDocument; diff --git a/build/webpack/webpack.extension.config.js b/build/webpack/webpack.extension.config.js index f559924fdd6b..b19caa9f6a7d 100644 --- a/build/webpack/webpack.extension.config.js +++ b/build/webpack/webpack.extension.config.js @@ -11,6 +11,8 @@ const configFileName = path.join(constants_1.ExtensionRootDir, 'tsconfig.extensi // Some modules will be pre-genearted and stored in out/.. dir and they'll be referenced via NormalModuleReplacementPlugin // We need to ensure they do not get bundled into the output (as they are large). const existingModulesInOutDir = common_1.getListOfExistingModulesInOutDir(); +// tslint:disable-next-line:no-var-requires no-require-imports +const FileManagerPlugin = require('filemanager-webpack-plugin'); const config = { mode: 'production', target: 'node', @@ -49,9 +51,9 @@ const config = { } ] }, - {enforce: 'post', test: /unicode-properties[\/\\]index.js$/, loader: "transform-loader?brfs"}, - {enforce: 'post', test: /fontkit[\/\\]index.js$/, loader: "transform-loader?brfs"}, - {enforce: 'post', test: /linebreak[\/\\]src[\/\\]linebreaker.js/, loader: "transform-loader?brfs"} + { enforce: 'post', test: /unicode-properties[\/\\]index.js$/, loader: 'transform-loader?brfs' }, + { enforce: 'post', test: /fontkit[\/\\]index.js$/, loader: 'transform-loader?brfs' }, + { enforce: 'post', test: /linebreak[\/\\]src[\/\\]linebreaker.js/, loader: 'transform-loader?brfs' } ] }, externals: [ @@ -60,9 +62,26 @@ const config = { ...existingModulesInOutDir ], plugins: [ - ...common_1.getDefaultPlugins('extension') + ...common_1.getDefaultPlugins('extension'), + // Copy pdfkit bits after extension builds. webpack can't handle pdfkit. + new FileManagerPlugin({ + onEnd: [ + { + copy: [ + { source: './node_modules/pdfkit/js/data/*.*', destination: './out/client/node_modules/data' }, + { source: './node_modules/pdfkit/js/pdfkit.js', destination: './out/client/node_modules/' } + ] + } + ] + }) ], resolve: { + alias:{ + // Pointing pdfkit to a dummy js file so webpack doesn't fall over. + // Since pdfkit has been externalized (it gets updated with the valid code by copying the pdfkit files + // into the right destination). + 'pdfkit':path.resolve(__dirname, 'pdfkit.js') + }, extensions: ['.ts', '.js'], plugins: [ new tsconfig_paths_webpack_plugin_1.TsconfigPathsPlugin({ configFile: configFileName }) diff --git a/build/webpack/webpack.extension.config.ts b/build/webpack/webpack.extension.config.ts index 4d9eba1ec88e..9b565d99e369 100644 --- a/build/webpack/webpack.extension.config.ts +++ b/build/webpack/webpack.extension.config.ts @@ -16,6 +16,9 @@ const configFileName = path.join(ExtensionRootDir, 'tsconfig.extension.json'); // We need to ensure they do not get bundled into the output (as they are large). const existingModulesInOutDir = getListOfExistingModulesInOutDir(); +// tslint:disable-next-line:no-var-requires no-require-imports +const FileManagerPlugin = require('filemanager-webpack-plugin'); + const config: Configuration = { mode: 'production', target: 'node', @@ -53,7 +56,11 @@ const config: Configuration = { loader: 'ts-loader' } ] - } + }, + {enforce: 'post', test: /unicode-properties[\/\\]index.js$/, loader: 'transform-loader?brfs'}, + {enforce: 'post', test: /fontkit[\/\\]index.js$/, loader: 'transform-loader?brfs'}, + {enforce: 'post', test: /pdfkit[\\\/]js[\\\/].*js$/, loader: 'transform-loader?brfs'}, + {enforce: 'post', test: /linebreak[\/\\]src[\/\\]linebreaker.js/, loader: 'transform-loader?brfs'} ] }, externals: [ @@ -62,7 +69,18 @@ const config: Configuration = { ...existingModulesInOutDir ], plugins: [ - ...getDefaultPlugins('extension') + ...getDefaultPlugins('extension'), + // Copy pdfkit bits after extension builds. webpack can't handle pdfkit. + new FileManagerPlugin({ + onEnd: [ + { + copy: [ + { source: './node_modules/pdfkit/js/data/*.*', destination: './out/client/node_modules/data' }, + { source: './node_modules/pdfkit/js/pdfkit.js', destination: './out/client/node_modules/' } + ] + } + ] + }) ], resolve: { extensions: ['.ts', '.js'], diff --git a/build/webpack/webpack.extension.dependencies.config.js b/build/webpack/webpack.extension.dependencies.config.js index 5a87744bfcb3..7186a206a71a 100644 --- a/build/webpack/webpack.extension.dependencies.config.js +++ b/build/webpack/webpack.extension.dependencies.config.js @@ -2,10 +2,11 @@ // Licensed under the MIT License. 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); +// tslint:disable-next-line: no-require-imports +const copyWebpackPlugin = require("copy-webpack-plugin"); const path = require("path"); const constants_1 = require("../constants"); const common_1 = require("./common"); -const copyWebpackPlugin = require("copy-webpack-plugin"); const entryItems = {}; common_1.nodeModulesToExternalize.forEach(moduleName => { entryItems[`node_modules/${moduleName}`] = `./node_modules/${moduleName}`; @@ -28,7 +29,10 @@ const config = { loader: path.join(__dirname, 'loaders', 'fixEvalRequire.js') } ] - } + }, + { enforce: 'post', test: /unicode-properties[\/\\]index.js$/, loader: 'transform-loader?brfs' }, + { enforce: 'post', test: /fontkit[\/\\]index.js$/, loader: 'transform-loader?brfs' }, + { enforce: 'post', test: /linebreak[\/\\]src[\/\\]linebreaker.js/, loader: 'transform-loader?brfs' } ] }, externals: [ @@ -48,6 +52,12 @@ const config = { ]) ], resolve: { + alias:{ + // Pointing pdfkit to a dummy js file so webpack doesn't fall over. + // Since pdfkit has been externalized (it gets updated with the valid code by copying the pdfkit files + // into the right destination). + 'pdfkit':path.resolve(__dirname, 'pdfkit.js') + }, extensions: ['.js'] }, output: { diff --git a/build/webpack/webpack.extension.dependencies.config.ts b/build/webpack/webpack.extension.dependencies.config.ts index 76c72bea9fba..f380ac8a77e6 100644 --- a/build/webpack/webpack.extension.dependencies.config.ts +++ b/build/webpack/webpack.extension.dependencies.config.ts @@ -3,11 +3,12 @@ 'use strict'; +// tslint:disable-next-line: no-require-imports +import copyWebpackPlugin = require('copy-webpack-plugin'); import * as path from 'path'; import * as webpack from 'webpack'; import { ExtensionRootDir } from '../constants'; import { getDefaultPlugins, nodeModulesToExternalize } from './common'; -import copyWebpackPlugin = require('copy-webpack-plugin'); const entryItems: Record = {}; nodeModulesToExternalize.forEach(moduleName => { @@ -32,7 +33,11 @@ const config: webpack.Configuration = { loader: path.join(__dirname, 'loaders', 'fixEvalRequire.js') } ] - } + }, + {enforce: 'post', test: /unicode-properties[\/\\]index.js$/, loader: 'transform-loader?brfs'}, + {enforce: 'post', test: /fontkit[\/\\]index.js$/, loader: 'transform-loader?brfs'}, + {enforce: 'post', test: /pdfkit[\\\/]js[\\\/].*js$/, loader: 'transform-loader?brfs'}, + {enforce: 'post', test: /linebreak[\/\\]src[\/\\]linebreaker.js/, loader: 'transform-loader?brfs'} ] }, externals: [ diff --git a/news/2 Fixes/6277.md b/news/2 Fixes/6277.md new file mode 100644 index 000000000000..03b333fff46e --- /dev/null +++ b/news/2 Fixes/6277.md @@ -0,0 +1 @@ +Fix pdf export in release bits. \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index f3c5cf528f37..15c526c350ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2644,6 +2644,60 @@ "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.0.tgz", "integrity": "sha1-NhOqRhSQZLPB8GB5Gb8dR4boKIk=" }, + "archiver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.0.0.tgz", + "integrity": "sha512-5QeR6Xc5hSA9X1rbQfcuQ6VZuUXOaEdB65Dhmk9duuRJHYif/ZyJfuyJqsQrj34PFjU5emv5/MmfgA8un06onw==", + "dev": true, + "requires": { + "archiver-utils": "^2.0.0", + "async": "^2.0.0", + "buffer-crc32": "^0.2.1", + "glob": "^7.0.0", + "readable-stream": "^2.0.0", + "tar-stream": "^1.5.0", + "zip-stream": "^2.0.1" + }, + "dependencies": { + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + } + } + }, + "archiver-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.0.0.tgz", + "integrity": "sha512-JRBgcVvDX4Mwu2RBF8bBaHcQCSxab7afsxAPYDQ5W+19quIPP5CfKE7Ql+UHs9wYvwsaNR8oDuhtf5iqrKmzww==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "graceful-fs": "^4.1.0", + "lazystream": "^1.0.0", + "lodash.assign": "^4.2.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.toarray": "^4.4.0", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } + } + }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -5170,6 +5224,18 @@ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, + "compress-commons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "dev": true, + "requires": { + "buffer-crc32": "^0.2.1", + "crc32-stream": "^2.0.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5425,6 +5491,189 @@ } } }, + "cpx": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/cpx/-/cpx-1.5.0.tgz", + "integrity": "sha1-GFvgGFEdhycN7czCkxceN2VauI8=", + "dev": true, + "requires": { + "babel-runtime": "^6.9.2", + "chokidar": "^1.6.0", + "duplexer": "^0.1.1", + "glob": "^7.0.5", + "glob2base": "^0.0.12", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "resolve": "^1.1.7", + "safe-buffer": "^5.0.1", + "shell-quote": "^1.6.1", + "subarg": "^1.0.0" + }, + "dependencies": { + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + } + } + }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "requires": { + "buffer": "^5.1.0" + }, + "dependencies": { + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + } + } + }, + "crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "dev": true, + "requires": { + "crc": "^3.4.4", + "readable-stream": "^2.0.0" + } + }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -7120,6 +7369,57 @@ } } }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "^2.1.0" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -7456,6 +7756,39 @@ "integrity": "sha512-bTrKkzzZI6wH+NXhyD3SOXtb2zXTw2SbwI2RxUlRcXVsnN7jNL5hJzVQLYv7FOQhxFkK4XWdAflEaWFpaLLWpQ==", "dev": true }, + "filemanager-webpack-plugin": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/filemanager-webpack-plugin/-/filemanager-webpack-plugin-2.0.5.tgz", + "integrity": "sha512-Yj5XIdKI2AN2r66uZc4MZ/n18SMqe2KKlkAqHHMW1OwveDs2Vc5129CpbFcI73rq/rjqso+2HsxieS7u5sx6XA==", + "dev": true, + "requires": { + "archiver": "^3.0.0", + "cpx": "^1.5.0", + "fs-extra": "^7.0.0", + "make-dir": "^1.1.0", + "mv": "^2.1.1", + "rimraf": "^2.6.2" + }, + "dependencies": { + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, "filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", @@ -7528,6 +7861,12 @@ "pkg-dir": "^2.0.0" } }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, "find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -8588,6 +8927,42 @@ "path-is-absolute": "^1.0.0" } }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -8702,6 +9077,15 @@ } } }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "^0.1.1" + } + }, "global": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", @@ -10183,6 +10567,21 @@ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", "dev": true }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -10316,6 +10715,18 @@ "isobject": "^3.0.1" } }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -11551,6 +11962,12 @@ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", "dev": true }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true + }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -11569,6 +11986,18 @@ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, "lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", @@ -11599,6 +12028,12 @@ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", "dev": true }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, "lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", @@ -11623,6 +12058,18 @@ "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", "dev": true }, + "lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", + "dev": true + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=", + "dev": true + }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -11863,6 +12310,12 @@ "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==", "dev": true }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, "md5": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", @@ -12531,6 +12984,41 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, + "mv": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", + "dev": true, + "requires": { + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "rimraf": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", + "dev": true, + "requires": { + "glob": "^6.0.1" + } + } + } + }, "named-js-regexp": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/named-js-regexp/-/named-js-regexp-1.3.3.tgz", @@ -12562,6 +13050,12 @@ "to-regex": "^3.0.1" } }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", + "dev": true + }, "nearley": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.15.1.tgz", @@ -13358,6 +13852,27 @@ "make-iterator": "^1.0.0" } }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -13745,6 +14260,35 @@ "path-root": "^0.1.1" } }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -14186,6 +14730,12 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, "pretty-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", @@ -14426,6 +14976,25 @@ "ret": "~0.1.10" } }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, "randombytes": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", @@ -14938,6 +15507,15 @@ "private": "^0.1.6" } }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -16634,6 +17212,15 @@ "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==", "dev": true }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "^1.1.0" + } + }, "sudo-prompt": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-8.2.0.tgz", @@ -19978,6 +20565,17 @@ "integrity": "sha512-kKfnnYkbTfrAdd0xICNFw7Atm8nKpLcLv9AZGEt+kczL/WQVai4e2V6ZN8U/O+iI6WrNuJjNNOyu4zfhl9D3Hg==", "dev": true }, + "zip-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.0.1.tgz", + "integrity": "sha512-c+eUhhkDpaK87G/py74wvWLtz2kzMPNCCkUApkun50ssE0oQliIQzWpTnwjB+MTKVIf2tGzIgHyqW/Y+W77ecQ==", + "dev": true, + "requires": { + "archiver-utils": "^2.0.0", + "compress-commons": "^1.2.0", + "readable-stream": "^2.0.0" + } + }, "zone.js": { "version": "0.7.6", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.7.6.tgz", diff --git a/package.json b/package.json index e98f51f10bd8..b202aaa3bb22 100644 --- a/package.json +++ b/package.json @@ -2336,6 +2336,7 @@ "event-stream": "3.3.4", "expose-loader": "^0.7.5", "file-loader": "^2.0.0", + "filemanager-webpack-plugin": "^2.0.5", "flat": "^4.0.0", "gulp": "^4.0.0", "gulp-azure-storage": "^0.9.0", diff --git a/package.nls.json b/package.nls.json index c5af11a52d0d..2bd9ebdb872c 100644 --- a/package.nls.json +++ b/package.nls.json @@ -273,5 +273,6 @@ "DataScience.editSection" : "Input new cells here.", "DataScience.restartKernelMessageDontAskAgain" : "Yes, and Don't Ask Again", "DataScience.selectedImageListLabel" : "Selected Image", - "DataScience.imageListLabel" : "Image" + "DataScience.imageListLabel" : "Image", + "DataScience.exportImageFailed" : "Error exporting image: {0}" } diff --git a/src/client/common/utils/localize.ts b/src/client/common/utils/localize.ts index cc4d5096c446..621f5e328141 100644 --- a/src/client/common/utils/localize.ts +++ b/src/client/common/utils/localize.ts @@ -202,6 +202,7 @@ export namespace DataScience { export const editSection = localize('DataScience.editSection', 'Input new cells here.'); export const selectedImageListLabel = localize('DataScience.selectedImageListLabel', 'Selected Image'); export const imageListLabel = localize('DataScience.imageListLabel', 'Image'); + export const exportImageFailed = localize('DataScience.exportImageFailed', 'Error exporting image: {0}'); } export namespace DebugConfigStrings { diff --git a/src/client/datascience/plotting/plotViewer.ts b/src/client/datascience/plotting/plotViewer.ts index 0b8c5504ff89..bc040601a0cf 100644 --- a/src/client/datascience/plotting/plotViewer.ts +++ b/src/client/datascience/plotting/plotViewer.ts @@ -5,11 +5,13 @@ import '../../common/extensions'; import { inject, injectable } from 'inversify'; import * as path from 'path'; -import * as pdfkit from 'pdfkit'; import { Event, EventEmitter, ViewColumn } from 'vscode'; +import { traceInfo } from '../../../client/common/logger'; +import { createDeferred } from '../../../client/common/utils/async'; import { IApplicationShell, IWebPanelProvider, IWorkspaceService } from '../../common/application/types'; import { EXTENSION_ROOT_DIR } from '../../common/constants'; +import { traceError } from '../../common/logger'; import { IFileSystem } from '../../common/platform/types'; import { IConfigurationService, IDisposable } from '../../common/types'; import * as localize from '../../common/utils/localize'; @@ -113,7 +115,7 @@ export class PlotViewer extends WebViewHost implements IPlot } private async exportPlot(payload: IExportPlotRequest) : Promise { - + traceInfo('exporting plot...'); const filtersObject: Record = {}; filtersObject[localize.DataScience.pdfFilter()] = ['pdf']; filtersObject[localize.DataScience.pngFilter()] = ['png']; @@ -124,30 +126,47 @@ export class PlotViewer extends WebViewHost implements IPlot saveLabel: localize.DataScience.exportPlotTitle(), filters: filtersObject }); - if (file) { - const ext = path.extname(file.fsPath); - switch (ext.toLowerCase()) { - case '.pdf': - // tslint:disable-next-line: no-require-imports - const SVGtoPDF = require('svg-to-pdfkit'); - const doc = new pdfkit(); - SVGtoPDF(doc, payload.svg, 0, 0); - doc.pipe(this.fileSystem.createWriteStream(file.fsPath)); - doc.end(); - break; - - case '.png': - const buffer = new Buffer(payload.png.replace('data:image/png;base64', ''), 'base64'); - await this.fileSystem.writeFile(file.fsPath, buffer); - break; - - default: - case '.svg': - // This is the easy one: - await this.fileSystem.writeFile(file.fsPath, payload.svg); - break; + try { + if (file) { + const ext = path.extname(file.fsPath); + switch (ext.toLowerCase()) { + case '.pdf': + traceInfo('Attempting pdf write...'); + // Import here since pdfkit is so huge. + // tslint:disable-next-line: no-require-imports + const SVGtoPDF = require('svg-to-pdfkit'); + const deferred = createDeferred(); + // tslint:disable-next-line: no-require-imports + const pdfkit = require('pdfkit'); + const doc = new pdfkit(); + const ws = this.fileSystem.createWriteStream(file.fsPath); + traceInfo(`Writing pdf to ${file.fsPath}`); + ws.on('finish', () => deferred.resolve); + SVGtoPDF(doc, payload.svg, 0, 0); + doc.pipe(ws); + doc.end(); + traceInfo(`Finishing pdf to ${file.fsPath}`); + await deferred.promise; + traceInfo(`Completed pdf to ${file.fsPath}`); + break; + + case '.png': + const buffer = new Buffer(payload.png.replace('data:image/png;base64', ''), 'base64'); + await this.fileSystem.writeFile(file.fsPath, buffer); + break; + + default: + case '.svg': + // This is the easy one: + await this.fileSystem.writeFile(file.fsPath, payload.svg); + break; + } + } + } catch (e) { + traceError(e); + this.applicationShell.showErrorMessage(localize.DataScience.exportImageFailed().format(e)); } }