├── .eslintrc.json ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── package.json ├── paths.js ├── scripts └── generate-typings ├── webpack.config.external.js ├── webpack.config.standalone.js ├── webpack ├── createConfig.js ├── loaders │ ├── babel.js │ ├── umd.js │ └── wrap.js └── stub.js └── yarn.lock /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@timkendrick/eslint-config", 3 | "rules": { 4 | "import/no-extraneous-dependencies": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dist/ 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "monaco-html"] 2 | path = submodules/monaco-html 3 | url = https://github.com/Microsoft/monaco-html.git 4 | [submodule "monaco-css"] 5 | path = submodules/monaco-css 6 | url = https://github.com/Microsoft/monaco-css.git 7 | [submodule "monaco-json"] 8 | path = submodules/monaco-json 9 | url = https://github.com/Microsoft/monaco-json.git 10 | [submodule "monaco-languages"] 11 | path = submodules/monaco-languages 12 | url = https://github.com/Microsoft/monaco-languages.git 13 | [submodule "monaco-typescript"] 14 | path = submodules/monaco-typescript 15 | url = https://github.com/Microsoft/monaco-typescript.git 16 | [submodule "vscode"] 17 | path = submodules/vscode 18 | url = https://github.com/Microsoft/vscode.git 19 | [submodule "vscode-css-languageservice"] 20 | path = submodules/vscode-css-languageservice 21 | url = https://github.com/Microsoft/vscode-css-languageservice.git 22 | [submodule "vscode-json-languageservice"] 23 | path = submodules/vscode-json-languageservice 24 | url = https://github.com/Microsoft/vscode-json-languageservice.git 25 | [submodule "vscode-html-languageservice"] 26 | path = submodules/vscode-html-languageservice 27 | url = https://github.com/Microsoft/vscode-html-languageservice.git 28 | [submodule "vscode-languageserver-node"] 29 | path = submodules/vscode-languageserver-node 30 | url = https://github.com/Microsoft/vscode-languageserver-node.git 31 | [submodule "vscode-nls"] 32 | path = submodules/vscode-nls 33 | url = https://github.com/Microsoft/vscode-nls.git 34 | [submodule "vscode-uri"] 35 | path = submodules/vscode-uri 36 | url = https://github.com/Microsoft/vscode-uri.git 37 | [submodule "jsonc-parser"] 38 | path = submodules/jsonc-parser 39 | url = https://github.com/Microsoft/node-jsonc-parser.git 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Tim Kendrick 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @timkendrick/monaco-editor 2 | [![npm version](https://img.shields.io/npm/v/@timkendrick/monaco-editor.svg)](https://www.npmjs.com/package/@timkendrick/monaco-editor) 3 | ![Stability](https://img.shields.io/badge/stability-experimental-yellow.svg) 4 | 5 | > CommonJS/Webpack compatible Monaco editor 6 | 7 | This module exports a prebuilt UMD bundle that exposes a standalone [Monaco editor](https://microsoft.github.io/monaco-editor/). 8 | 9 | ## Installation 10 | 11 | ```bash 12 | npm install @timkendrick/monaco-editor --save 13 | ``` 14 | 15 | ## Usage 16 | 17 | The editor comes in two versions: standalone and external. 18 | 19 | In the standalone version, the accompanying CSS and web worker scripts are all compiled into the main JavaScript bundle, avoiding the need to serve external assets separately. 20 | 21 | In the external version, the accompanying CSS and web worker scripts are provided as separate assets that must be served separately. 22 | 23 | ### Importing the standalone version 24 | 25 | As a CommonJS module: 26 | 27 | ```js 28 | const monaco = require('@timkendrick/monaco-editor'); 29 | 30 | monaco.editor.create(...); 31 | ``` 32 | 33 | As an ECMAScript module: 34 | 35 | ```js 36 | import * as monaco from '@timkendrick/monaco-editor'; 37 | 38 | monaco.editor.create(...); 39 | ``` 40 | 41 | As a global variable: 42 | 43 | ```js 44 | window.monaco.editor.create(...); 45 | ``` 46 | 47 | ### Using the external version 48 | 49 | #### Setup 50 | 51 | Additional CSS and worker scripts are located in the `dist/external` directory. These must be loaded by the browser at runtime. 52 | 53 | The `monaco.css` file must be loaded as a stylesheet, and the path to directory containing the worker scripts can be specified as `window.MonacoEnvironment.baseUrl`: 54 | 55 | ```html 56 | 57 | 58 | 59 | 60 | 61 | 66 | 67 | 68 | 69 | ``` 70 | 71 | #### Importing the external version 72 | 73 | As a CommonJS module: 74 | 75 | ```js 76 | const monaco = require('@timkendrick/monaco-editor/dist/external'); 77 | 78 | monaco.editor.create(...); 79 | ``` 80 | 81 | As an ECMAScript module: 82 | 83 | ```js 84 | import * as monaco from '@timkendrick/monaco-editor/dist/external'; 85 | 86 | monaco.editor.create(...); 87 | ``` 88 | 89 | As a global variable: 90 | 91 | ```js 92 | window.monaco.editor.create(...); 93 | ``` 94 | 95 | ## Editor API 96 | 97 | For full usage instructions, see the [Monaco API Docs](https://microsoft.github.io/monaco-editor/api/index.html). 98 | 99 | ## Configuration 100 | 101 | The editor configuration is based on the AMD version in the [Microsoft/monaco-editor](https://github.com/Microsoft/monaco-editor) repository. 102 | 103 | To generate custom builds, see the [@timkendrick/monaco-editor-loader](https://www.npmjs.com/package/@timkendrick/monaco-editor-loader) Webpack loader. 104 | 105 | ## Building from source 106 | 107 | ```bash 108 | git clone https://github.com/timkendrick/monaco-editor.git 109 | cd monaco-editor 110 | git submodule update --init 111 | npm install 112 | 113 | npm run build 114 | ``` 115 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@timkendrick/monaco-editor", 3 | "version": "0.0.9", 4 | "description": "CommonJS/Webpack compatible Monaco editor", 5 | "main": "dist/standalone/index.js", 6 | "typings": "dist/standalone/index.d.ts", 7 | "scripts": { 8 | "build:standalone": "cross-env NODE_ENV=production webpack --config webpack.config.standalone && npm run typings:standalone", 9 | "build:external": "cross-env NODE_ENV=production webpack --config webpack.config.external && npm run typings:external", 10 | "typings:standalone": "./scripts/generate-typings dist/standalone/index.d.ts", 11 | "typings:external": "./scripts/generate-typings dist/external/index.d.ts", 12 | "build": "npm run clean && npm run build:standalone && npm run build:external", 13 | "clean": "del dist", 14 | "prepublish": "npm run build" 15 | }, 16 | "files": [ 17 | "dist" 18 | ], 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/timkendrick/monaco-editor.git" 22 | }, 23 | "author": "Tim Kendrick ", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/timkendrick/monaco-editor/issues" 27 | }, 28 | "homepage": "https://github.com/timkendrick/monaco-editor", 29 | "keywords": [ 30 | "monaco", 31 | "editor", 32 | "webpack", 33 | "commonjs", 34 | "module" 35 | ], 36 | "devDependencies": { 37 | "@babel/core": "7.0.0-beta.35", 38 | "@timkendrick/babel-preset-vscode": "0.0.1", 39 | "@timkendrick/eslint-config": "^1.0.0", 40 | "@timkendrick/monaco-editor-loader": "0.0.7", 41 | "babel-loader": "8.0.0-beta.0", 42 | "cross-env": "5.1.3", 43 | "css-loader": "0.28.7", 44 | "del-cli": "1.1.0", 45 | "escape-string-regexp": "1.0.5", 46 | "eslint": "^4.0.0", 47 | "extract-text-webpack-plugin": "3.0.2", 48 | "file-loader": "1.1.6", 49 | "lines-and-columns": "1.1.6", 50 | "loader-utils": "1.1.0", 51 | "merge-source-map": "1.0.4", 52 | "monaco-editor": "0.10.1", 53 | "progress-bar-webpack-plugin": "1.10.0", 54 | "source-map": "0.6.1", 55 | "source-map-support": "0.5.0", 56 | "style-loader": "0.19.1", 57 | "ts-loader": "3.2.0", 58 | "typescript": "2.6.2", 59 | "uglifyjs-webpack-plugin": "1.1.8", 60 | "url-loader": "0.6.2", 61 | "vscode-css-languageservice": "3.0.3", 62 | "vscode-html-languageservice": "2.0.14", 63 | "vscode-json-languageservice": "3.0.4", 64 | "vscode-languageserver-types": "3.5.0", 65 | "webpack": "3.11.0", 66 | "webpack-cli": "2.0.1" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /paths.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | function getSubmodulePath(filePath) { 5 | return path.join(__dirname, 'submodules', filePath); 6 | } 7 | 8 | module.exports = { 9 | tsconfig: getSubmodulePath('vscode/src/tsconfig.json'), 10 | entry: getSubmodulePath('vscode/src/vs/editor/editor.main.ts'), 11 | modules: [ 12 | { 13 | name: 'vs', 14 | root: getSubmodulePath('vscode/src/vs'), 15 | }, 16 | { 17 | name: 'vs/basic-languages', 18 | root: getSubmodulePath('monaco-languages/src'), 19 | main: 'monaco.contribution.ts', 20 | include: true, 21 | }, 22 | { 23 | name: 'vs/language/css', 24 | root: getSubmodulePath('monaco-css/src'), 25 | main: 'monaco.contribution.ts', 26 | include: true, 27 | }, 28 | { 29 | name: 'vs/language/html', 30 | root: getSubmodulePath('monaco-html/src'), 31 | main: 'monaco.contribution.ts', 32 | include: true, 33 | }, 34 | { 35 | name: 'vs/language/json', 36 | root: getSubmodulePath('monaco-json/src'), 37 | main: 'monaco.contribution.ts', 38 | include: true, 39 | }, 40 | { 41 | name: 'vs/language/typescript/src', 42 | root: getSubmodulePath('monaco-typescript/src'), 43 | main: 'monaco.contribution.ts', 44 | include: true, 45 | }, 46 | { 47 | name: 'vscode-css-languageservice', 48 | root: getSubmodulePath('vscode-css-languageservice/src'), 49 | main: 'cssLanguageService.ts', 50 | }, 51 | { 52 | name: 'vscode-html-languageservice', 53 | root: getSubmodulePath('vscode-html-languageservice/src'), 54 | main: 'htmlLanguageService.ts', 55 | }, 56 | { 57 | name: 'vscode-json-languageservice', 58 | root: getSubmodulePath('vscode-json-languageservice/src'), 59 | main: 'jsonLanguageService.ts', 60 | }, 61 | { 62 | name: 'vscode-languageserver-types', 63 | root: getSubmodulePath('vscode-languageserver-node/types/src'), 64 | main: 'main.ts', 65 | }, 66 | { 67 | name: 'vscode-nls', 68 | root: getSubmodulePath('vscode-nls/src'), 69 | main: 'main.ts', 70 | }, 71 | { 72 | name: 'vscode-uri', 73 | root: getSubmodulePath('vscode-uri/lib'), 74 | main: 'index.ts', 75 | }, 76 | { 77 | name: 'jsonc-parser', 78 | root: getSubmodulePath('jsonc-parser/src'), 79 | main: 'main.ts', 80 | }, 81 | ], 82 | workers: [ 83 | { 84 | name: 'workerMain.js', 85 | main: getSubmodulePath('vscode/src/vs/base/worker/workerMain.ts'), 86 | includes: [ 87 | getSubmodulePath('vscode/src/vs/editor/common/services/editorSimpleWorker.ts'), 88 | ], 89 | }, 90 | ], 91 | contexts: [ 92 | { 93 | path: path.dirname(getSubmodulePath('vscode/src/vs/base/worker/workerMain.ts')), 94 | includes: { 95 | 'vs/base/common/worker/simpleWorker': getSubmodulePath('vscode/src/vs/base/common/worker/simpleWorker.ts'), 96 | }, 97 | }, 98 | { 99 | path: path.dirname(getSubmodulePath('vscode/src/vs/base/common/worker/simpleWorker.ts')), 100 | includes: { 101 | 'vs/editor/common/services/editorSimpleWorker': getSubmodulePath('vscode/src/vs/editor/common/services/editorSimpleWorker.ts'), 102 | }, 103 | }, 104 | { 105 | path: path.dirname(getSubmodulePath('vscode/src/vs/editor/common/services/editorSimpleWorker.ts')), 106 | includes: { 107 | 'vs/language/css/cssWorker': getSubmodulePath('monaco-css/src/cssWorker.ts'), 108 | 'vs/language/html/htmlWorker': getSubmodulePath('monaco-html/src/htmlWorker.ts'), 109 | 'vs/language/json/jsonWorker': getSubmodulePath('monaco-json/src/jsonWorker.ts'), 110 | 'vs/language/typescript/src/worker': getSubmodulePath('monaco-typescript/src/worker.ts'), 111 | }, 112 | }, 113 | { 114 | path: path.dirname(getSubmodulePath('monaco-languages/src/monaco.contribution.ts')), 115 | includes: ( 116 | fs.readdirSync(getSubmodulePath('monaco-languages/src')).reduce( 117 | (acc, filename) => Object.assign(acc, { 118 | [`./${path.basename(filename, path.extname(filename))}`]: 119 | path.join(getSubmodulePath('monaco-languages/src'), filename), 120 | }), 121 | {} 122 | ) 123 | ), 124 | }, 125 | ], 126 | umd: [ 127 | getSubmodulePath('vscode-css-languageservice/src/data/browsers.js'), 128 | ], 129 | }; 130 | 131 | -------------------------------------------------------------------------------- /scripts/generate-typings: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const fs = require('fs'); 3 | 4 | const args = process.argv.slice(2); 5 | const outputPath = args[0]; 6 | 7 | if (!outputPath) { 8 | process.stderr.write('No output filename specified\n'); 9 | process.exit(1); 10 | } 11 | 12 | const typingsPath = require.resolve('monaco-editor/monaco.d.ts'); 13 | const exportDeclaration = 'export = monaco;'; 14 | 15 | const typingsSource = fs.readFileSync(typingsPath, 'utf8'); 16 | const outputSource = `${typingsSource}\n\n${exportDeclaration}\n`; 17 | 18 | fs.writeFileSync(outputPath, outputSource); 19 | -------------------------------------------------------------------------------- /webpack.config.external.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const createConfig = require('./webpack/createConfig'); 4 | const paths = require('./paths'); 5 | 6 | module.exports = createConfig(paths, { 7 | outputPath: path.join(__dirname, 'dist', 'external'), 8 | library: 'monaco', 9 | inline: false, 10 | }); 11 | -------------------------------------------------------------------------------- /webpack.config.standalone.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const createConfig = require('./webpack/createConfig'); 4 | const paths = require('./paths'); 5 | 6 | module.exports = createConfig(paths, { 7 | outputPath: path.join(__dirname, 'dist', 'standalone'), 8 | library: 'monaco', 9 | inline: true, 10 | }); 11 | -------------------------------------------------------------------------------- /webpack/createConfig.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const escapeStringRegexp = require('escape-string-regexp'); 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 5 | const ProgressBarPlugin = require('progress-bar-webpack-plugin'); 6 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); 7 | 8 | module.exports = function createConfig(paths, { outputPath, inline, library }) { 9 | return { 10 | target: 'web', 11 | devtool: 'source-map', 12 | output: { 13 | path: outputPath, 14 | filename: 'index.js', 15 | libraryTarget: 'umd', 16 | library, 17 | }, 18 | // Load main entry point using custom Monaco Editor loader 19 | entry: getMonacoEntryPath(paths.entry, { 20 | modules: paths.modules, 21 | workers: paths.workers, 22 | workerOptions: { 23 | inline, 24 | filename: paths.workers.length > 1 ? `${library}.worker.[id].js` : `${library}.worker.js`, 25 | }, 26 | }), 27 | resolve: { 28 | alias: { 29 | // Define global module aliases for extensions etc 30 | ...getModuleAliases(paths.modules), 31 | // HACK: Prevent runtime error when importing unused "fs" module 32 | fs: require.resolve('./stub'), 33 | // HACK: Pending resolution of https://github.com/evanw/node-source-map-support/pull/198 34 | 'source-map-support': require.resolve('source-map-support/browser-source-map-support'), 35 | }, 36 | extensions: ['.ts', '.js', '.json'], 37 | }, 38 | node: { 39 | // HACK: Disabled due to some modules assuming that a global "process" object implies Node.js 40 | process: false, 41 | }, 42 | module: { 43 | rules: [ 44 | { 45 | test: /\.css?$/, 46 | use: (inline ? [ 47 | { loader: 'style-loader' }, 48 | { loader: 'css-loader' }, 49 | ] : ExtractTextPlugin.extract({ 50 | fallback: 'style-loader', 51 | use: 'css-loader', 52 | })), 53 | }, 54 | { 55 | test: /\.(png|jpg|gif|svg|ttf|otf|eot|woff|woff2)$/, 56 | use: [ 57 | { 58 | loader: 'url-loader', 59 | }, 60 | ], 61 | }, 62 | { 63 | test: /\.tsx?$/, 64 | use: [ 65 | { 66 | // HACK: Use custom babel loader due to babel-loader not processing input source maps 67 | // https://github.com/babel/babel/issues/5408 68 | loader: require.resolve('./loaders/babel'), 69 | options: { 70 | presets: [ 71 | // Custom Babel preset to convert VS Code AMD modules to CommonJS modules 72 | '@timkendrick/babel-preset-vscode', 73 | ], 74 | }, 75 | }, 76 | { 77 | loader: 'ts-loader', 78 | options: { 79 | transpileOnly: true, 80 | configFile: paths.tsconfig, 81 | compilerOptions: { 82 | module: 'commonjs', 83 | sourceMap: true, 84 | }, 85 | }, 86 | }, 87 | ], 88 | }, 89 | { 90 | // HACK: Wrap UMD modules with top-level require() shim to avoid runtime webpack errors 91 | test: paths.umd, 92 | use: [ 93 | { loader: require.resolve('./loaders/umd') }, 94 | ], 95 | }, 96 | ], 97 | }, 98 | plugins: [ 99 | // Create contexts for runtime require expressions 100 | ...getDynamicRequireContextPlugins(paths.contexts), 101 | // HACK: Required for ts-loader to work correctly within webpack v4 102 | new webpack.LoaderOptionsPlugin({ options: {} }), 103 | ...(inline ? [] : [new ExtractTextPlugin(`${library}.css`)]), 104 | new UglifyJsPlugin({ 105 | parallel: true, 106 | sourceMap: true, 107 | }), 108 | new ProgressBarPlugin(), 109 | ], 110 | }; 111 | }; 112 | 113 | function getModuleAliases(modules) { 114 | return modules 115 | .sort((a, b) => ( 116 | a.name.startsWith(`${b.name}/`) || b.name.startsWith(`${a.name}/`) 117 | ? b.name.length - a.name.length 118 | : 0 119 | )) 120 | .reduce((acc, module) => Object.assign( 121 | acc, 122 | (module.main ? { [`${module.name}$`]: path.join(module.root, module.main) } : undefined), 123 | { [module.name]: module.root } 124 | ), {}); 125 | } 126 | 127 | function getMonacoEntryPath(entry, options) { 128 | return `@timkendrick/monaco-editor-loader?${JSON.stringify(options)}!${entry}`; 129 | } 130 | 131 | function getDynamicRequireContextPlugins(contexts) { 132 | const includesByPath = contexts.reduce((acc, context) => Object.assign(acc, { 133 | [context.path]: { ...acc[context.path], ...context.includes }, 134 | }), {}); 135 | return Object.keys(includesByPath).map( 136 | (contextPath) => new webpack.ContextReplacementPlugin( 137 | new RegExp(escapeStringRegexp(contextPath)), 138 | '', 139 | includesByPath[contextPath] 140 | ) 141 | ); 142 | } 143 | -------------------------------------------------------------------------------- /webpack/loaders/babel.js: -------------------------------------------------------------------------------- 1 | // This loader ensures that source maps from previous loaders are merged into the output source map. 2 | // It can be removed once https://github.com/babel/babel/issues/5408 has been fixed. 3 | 4 | const babelLoader = require('babel-loader'); 5 | const mergeSourceMap = require('merge-source-map'); 6 | 7 | module.exports = function babel(input, inputSourceMap) { 8 | if (this.cacheable) { this.cacheable(); } 9 | const childContext = Object.assign(Object.create(this), { 10 | callback: (error, source, outputSourceMap) => { 11 | this.callback(error, source, mergeSourceMap(inputSourceMap, outputSourceMap)); 12 | }, 13 | }); 14 | return babelLoader.call(childContext, input); 15 | }; 16 | -------------------------------------------------------------------------------- /webpack/loaders/umd.js: -------------------------------------------------------------------------------- 1 | const loaderUtils = require('loader-utils'); 2 | 3 | module.exports.pitch = function pitch(remainingRequest) { 4 | return `module.exports = require(${loaderUtils.stringifyRequest(this, `!!${require.resolve('./wrap')}?${JSON.stringify({ 5 | before: '(function(require, define) {', 6 | after: `}(${[ 7 | 'function require(id) { throw new Error("Invalid dynamic require"); }', 8 | 'function define(id) { throw new Error("Invalid dynamic define"); })', 9 | ].join(', ')});`, 10 | })}!${remainingRequest}`)});`; 11 | }; 12 | -------------------------------------------------------------------------------- /webpack/loaders/wrap.js: -------------------------------------------------------------------------------- 1 | const loaderUtils = require('loader-utils'); 2 | const { default: LinesAndColumns } = require('lines-and-columns'); 3 | const { SourceMapConsumer, SourceMapGenerator } = require('source-map'); 4 | 5 | module.exports = function wrap(source, sourceMap) { 6 | const { before = '', after = '' } = loaderUtils.getOptions(this) || {}; 7 | if (!before && !after) { return this.callback(null, source, sourceMap); } 8 | const output = `${before || ''}${source}${after || ''}`; 9 | if (!this.sourceMap) { return output; } 10 | const map = createSourceMap(this.resourcePath, source); 11 | const getSourceLocation = getLinePositionFinder(source); 12 | const getOutputLocation = getLinePositionFinder(output); 13 | // eslint-disable-next-line no-plusplus 14 | for (let i = 0; i < output.length; i++) { 15 | map.addMapping({ 16 | source: this.resourcePath, 17 | original: getSourceLocation(Math.max(0, Math.min(source.length, i - before.length))), 18 | generated: getOutputLocation(i), 19 | }); 20 | } 21 | if (sourceMap) { map.applySourceMap(parseSourceMap(sourceMap)); } 22 | this.callback(null, output, JSON.parse(map.toString())); 23 | }; 24 | 25 | function getLinePositionFinder(string) { 26 | const positionFinder = new LinesAndColumns(string); 27 | return (index) => { 28 | const location = positionFinder.locationForIndex(index); 29 | return { line: location.line + 1, column: location.column }; 30 | }; 31 | } 32 | 33 | function createSourceMap(filePath, source) { 34 | const map = new SourceMapGenerator({ file: filePath }); 35 | map.setSourceContent(filePath, source); 36 | return map; 37 | } 38 | 39 | function parseSourceMap(sourceMap) { 40 | return new SourceMapConsumer(typeof sourceMap === 'string' ? JSON.parse(sourceMap) : sourceMap); 41 | } 42 | -------------------------------------------------------------------------------- /webpack/stub.js: -------------------------------------------------------------------------------- 1 | module.exports = null; 2 | --------------------------------------------------------------------------------