Rename to webpack-plugin

This commit is contained in:
Alex Dima 2021-11-15 16:16:53 +01:00
parent db6aec351b
commit a21839d00d
No known key found for this signature in database
GPG key ID: 39563C1504FDD0C9
25 changed files with 5 additions and 5 deletions

63
webpack-plugin/.github/commands.yml vendored Normal file
View file

@ -0,0 +1,63 @@
{
perform: true,
commands:
[
{
type: 'comment',
name: 'question',
allowUsers: [],
action: 'updateLabels',
addLabel: '*question'
},
{
type: 'label',
name: '*question',
allowTriggerByBot: true,
action: 'close',
comment: "Please ask your question on [StackOverflow](https://stackoverflow.com/questions/tagged/monaco-editor). We have a great community over [there](https://stackoverflow.com/questions/tagged/monaco-editor). They have already answered hundreds of questions and are happy to answer yours as well. You can also try [searching through existing issues](https://github.com/microsoft/monaco-editor/issues?utf8=%E2%9C%93&q=is%3Aissue+), looking at [API usage samples](https://microsoft.github.io/monaco-editor/playground.html) or at [integration samples](https://github.com/Microsoft/monaco-editor-samples). See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!"
},
{
type: 'label',
name: '*out-of-scope',
allowTriggerByBot: true,
action: 'close',
comment: "We closed this issue because we don't plan to address it in the foreseeable future. You can find more detailed information about our decision-making process [here](https://aka.ms/vscode-out-of-scope). If you disagree and feel that this issue is crucial: We are happy to listen and to reconsider.\n\nIf you wonder what we are up to, please see our [roadmap](https://aka.ms/vscoderoadmap) and [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nThanks for your understanding and happy coding!"
},
{
type: 'label',
name: '*as-designed',
allowTriggerByBot: true,
action: 'close',
comment: "The described behavior is how it is expected to work. If you disagree, please explain what is expected and what is not in more detail. See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!"
},
{
type: 'label',
name: '*english-please',
allowTriggerByBot: true,
action: 'close',
comment: 'This issue is being closed because its description is not in English, that makes it hard for us to work on it. Please open a new issue with an English description. You might find [Bing Translator](https://www.bing.com/translator) useful.'
},
{
type: 'comment',
name: 'duplicate',
allowUsers: [],
action: 'updateLabels',
addLabel: '*duplicate'
},
{
type: 'label',
name: '*duplicate',
allowTriggerByBot: true,
action: 'close',
comment: "Thanks for creating this issue! We figured it's covering the same as another one we already have. Thus, we closed this one as a duplicate. You can search for existing issues [here](https://github.com/Microsoft/monaco-editor/issues). See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!"
},
{
type: 'comment',
name: 'needsMoreInfo',
allowUsers: [],
action: 'updateLabels',
addLabel: 'needs more info',
comment: "Thanks for creating this issue! We figured it's missing some basic information or in some other way doesn't follow our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines. Please take the time to review these and update the issue.\n\nHappy Coding!"
}
]
}

1
webpack-plugin/.github/locker.yml vendored Normal file
View file

@ -0,0 +1 @@
{ daysAfterClose: 45, daysSinceLastUpdate: 3, ignoredLabels: ['*out-of-scope'], perform: true }

View file

@ -0,0 +1,6 @@
{
daysUntilClose: 7,
needsMoreInfoLabel: 'needs more info',
perform: true,
closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity. See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!"
}

View file

@ -0,0 +1,2 @@
/src/
/test/

16
webpack-plugin/.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}/test/",
"name": "Launch Program",
"program": "${workspaceFolder}/node_modules/.bin/webpack",
"args": ["--config", "webpack.config.js"]
}
]
}

21
webpack-plugin/LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE

107
webpack-plugin/README.md Normal file
View file

@ -0,0 +1,107 @@
# Monaco Editor Webpack Loader Plugin
A plugin to simplify loading the [Monaco Editor](https://github.com/Microsoft/monaco-editor) with [webpack](https://webpack.js.org/).
## Installing
```sh
npm install monaco-editor-webpack-plugin
```
## Using
- `webpack.config.js`:
```js
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const path = require('path');
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js'
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.ttf$/,
use: ['file-loader']
}
]
},
plugins: [new MonacoWebpackPlugin()]
};
```
- `index.js`:
```js
import * as monaco from 'monaco-editor';
// or import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
// if shipping only a subset of the features & languages is desired
monaco.editor.create(document.getElementById('container'), {
value: 'console.log("Hello, world")',
language: 'javascript'
});
```
## Options
Options can be passed in to `MonacoWebpackPlugin`. They can be used to generate a smaller editor bundle by selecting only certain languages or only certain editor features:
- `filename` (`string`) - custom filename template for worker scripts, respects the same options as [loader-utils' interpolateName](https://github.com/webpack/loader-utils#interpolatename). Useful for adding content-based hashes so that files can be served with long-lived caching headers.
- default value: `'[name].worker.js'`.
- `publicPath` (`string`) - custom public path for worker scripts, overrides the public path from which files generated by this plugin will be served. This wins out over Webpack's dynamic runtime path and can be useful to avoid attempting to load workers cross-origin when using a CDN for other static resources. Use e.g. '/' if you want to load your resources from the current origin..
- default value: `''`.
- `languages` (`string[]`) - include only a subset of the languages supported.
- default value: <!-- LANGUAGES_BEGIN -->`['abap', 'apex', 'azcli', 'bat', 'bicep', 'cameligo', 'clojure', 'coffee', 'cpp', 'csharp', 'csp', 'css', 'dart', 'dockerfile', 'ecl', 'elixir', 'flow9', 'fsharp', 'go', 'graphql', 'handlebars', 'hcl', 'html', 'ini', 'java', 'javascript', 'json', 'julia', 'kotlin', 'less', 'lexon', 'liquid', 'lua', 'm3', 'markdown', 'mips', 'msdax', 'mysql', 'objective-c', 'pascal', 'pascaligo', 'perl', 'pgsql', 'php', 'pla', 'postiats', 'powerquery', 'powershell', 'protobuf', 'pug', 'python', 'qsharp', 'r', 'razor', 'redis', 'redshift', 'restructuredtext', 'ruby', 'rust', 'sb', 'scala', 'scheme', 'scss', 'shell', 'solidity', 'sophia', 'sparql', 'sql', 'st', 'swift', 'systemverilog', 'tcl', 'twig', 'typescript', 'vb', 'xml', 'yaml']`<!-- LANGUAGES_END -->.
Some languages share the same web worker. If one of the following languages is included, you must also include the language responsible for instantiating their shared worker:
| Language | Instantiator |
| ---------- | ------------ |
| javascript | typescript |
| handlebars | html |
| scss, less | css |
- `features` (`string[]`) - include only a subset of the editor features.
- default value: <!-- FEATURES_BEGIN -->`['accessibilityHelp', 'anchorSelect', 'bracketMatching', 'caretOperations', 'clipboard', 'codeAction', 'codelens', 'colorPicker', 'comment', 'contextmenu', 'coreCommands', 'cursorUndo', 'dnd', 'documentSymbols', 'find', 'folding', 'fontZoom', 'format', 'gotoError', 'gotoLine', 'gotoSymbol', 'hover', 'iPadShowKeyboard', 'inPlaceReplace', 'indentation', 'inlayHints', 'inlineCompletions', 'inspectTokens', 'linesOperations', 'linkedEditing', 'links', 'multicursor', 'parameterHints', 'quickCommand', 'quickHelp', 'quickOutline', 'referenceSearch', 'rename', 'smartSelect', 'snippets', 'suggest', 'toggleHighContrast', 'toggleTabFocusMode', 'transpose', 'unusualLineTerminators', 'viewportSemanticTokens', 'wordHighlighter', 'wordOperations', 'wordPartOperations']`<!-- FEATURES_END -->.
- excluded features: It is also possible to exclude certain default features prefixing them with an exclamation mark '!'.
- `globalAPI` (`boolean`) - specify whether the editor API should be exposed through a global `monaco` object or not. This option is applicable to `0.22.0` and newer version of `monaco-editor`. Since `0.22.0`, the ESM version of the monaco editor does no longer define a global `monaco` object unless `global.MonacoEnvironment = { globalAPI: true }` is set ([change log](https://github.com/microsoft/monaco-editor/blob/main/CHANGELOG.md#0220-29012021)).
- default value: `false`.
## Version Matrix
| `monaco-editor-webpack-plugin` | `monaco-editor` |
| ------------------------------ | -------------------------------------- |
| `6.*.*` | `0.30.*` |
| `5.*.*` | `0.29.*` |
| `4.*.*` | `0.25.*`, `0.26.*`, `0.27.*`, `0.28.*` |
| `3.*.*` | `0.22.*`, `0.23.*`, `0.24.*` |
| `2.*.*` | `0.21.*` |
| `1.9.*` | `0.20.*` |
| `1.8.*` | `0.19.*` |
| `1.7.*` | `0.18.*` |
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.microsoft.com.
When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

1331
webpack-plugin/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,46 @@
{
"name": "monaco-editor-webpack-plugin",
"version": "6.0.0",
"description": "A webpack plugin for the Monaco Editor",
"main": "out/index.js",
"typings": "./out/index.d.ts",
"scripts": {
"test": "node ./node_modules/webpack/bin/webpack.js --config test/webpack.config.js --progress",
"test-cross-origin": "node ./node_modules/webpack/bin/webpack.js --config test/webpack-cross-origin.config.js --progress",
"watch": "tsc -w -p tsconfig.json",
"import-editor": "node ./scripts/import-editor.js",
"prepublishOnly": "tsc -p tsconfig.json"
},
"repository": {
"type": "git",
"url": "git+https://github.com/microsoft/monaco-editor-webpack-plugin.git"
},
"keywords": [
"webpack",
"monaco",
"editor",
"loader"
],
"author": "Microsoft Corporation",
"license": "MIT",
"bugs": {
"url": "https://github.com/microsoft/monaco-editor-webpack-plugin/issues"
},
"homepage": "https://github.com/microsoft/monaco-editor-webpack-plugin#readme",
"peerDependencies": {
"webpack": "^4.5.0 || 5.x",
"monaco-editor": "0.30.x"
},
"devDependencies": {
"css-loader": "^5.1.1",
"file-loader": "^6.2.0",
"glob": "^7.1.6",
"style-loader": "^2.0.0",
"typescript": "^4.2.3",
"webpack": "^5.24.3",
"webpack-cli": "^4.5.0"
},
"dependencies": {
"loader-utils": "^2.0.0"
}
}

View file

@ -0,0 +1,291 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const glob = require('glob');
const path = require('path');
const fs = require('fs');
const customFeatureLabels = {
'vs/editor/browser/controller/coreCommands': 'coreCommands',
'vs/editor/contrib/caretOperations/caretOperations': 'caretOperations',
'vs/editor/contrib/caretOperations/transpose': 'transpose',
'vs/editor/contrib/colorPicker/colorDetector': 'colorDetector',
'vs/editor/contrib/rename/onTypeRename': 'onTypeRename',
'vs/editor/contrib/gotoSymbol/link/goToDefinitionAtPosition': 'gotoSymbol',
'vs/editor/contrib/snippet/snippetController2': 'snippets',
'vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess': 'gotoLine',
'vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess': 'quickCommand',
'vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess': 'quickOutline',
'vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess': 'quickHelp'
};
generateLanguages();
generateFeatures();
/**
* @returns { Promise<{ label: string; entry: string; }[]> }
*/
function getBasicLanguages() {
return new Promise((resolve, reject) => {
glob(
'./node_modules/monaco-editor/esm/vs/basic-languages/*/*.contribution.js',
{ cwd: path.dirname(__dirname) },
(err, files) => {
if (err) {
reject(err);
return;
}
resolve(
files.map((file) => {
const entry = file
.substring('./node_modules/monaco-editor/esm/'.length)
.replace(/\.js$/, '');
const label = path.basename(file).replace(/\.contribution\.js$/, '');
return {
label: label,
entry: entry
};
})
);
}
);
});
}
/**
* @returns { Promise<string[]> }
*/
function readAdvancedLanguages() {
return new Promise((resolve, reject) => {
glob(
'./node_modules/monaco-editor/esm/vs/language/*/monaco.contribution.js',
{ cwd: path.dirname(__dirname) },
(err, files) => {
if (err) {
reject(err);
return;
}
resolve(
files
.map((file) => file.substring('./node_modules/monaco-editor/esm/vs/language/'.length))
.map((file) => file.substring(0, file.length - '/monaco.contribution.js'.length))
);
}
);
});
}
/**
* @returns { Promise<{ label: string; entry: string; worker: { id: string; entry: string; }; }[]> }
*/
function getAdvancedLanguages() {
return readAdvancedLanguages().then((languages) => {
let result = [];
for (const lang of languages) {
let shortLang = lang === 'typescript' ? 'ts' : lang;
const entry = `vs/language/${lang}/monaco.contribution`;
checkFileExists(entry);
const workerId = `vs/language/${lang}/${shortLang}Worker`;
checkFileExists(workerId);
const workerEntry = `vs/language/${lang}/${shortLang}.worker`;
checkFileExists(workerEntry);
result.push({
label: lang,
entry: entry,
worker: {
id: workerId,
entry: workerEntry
}
});
}
return result;
});
function checkFileExists(moduleName) {
const filePath = path.join(
__dirname,
'..',
'node_modules/monaco-editor/esm',
`${moduleName}.js`
);
if (!fs.existsSync(filePath)) {
console.error(`Could not find ${filePath}.`);
process.exit(1);
}
}
}
function generateLanguages() {
return Promise.all([getBasicLanguages(), getAdvancedLanguages()]).then(
([basicLanguages, advancedLanguages]) => {
basicLanguages.sort(strcmp);
advancedLanguages.sort(strcmp);
let i = 0,
len = basicLanguages.length;
let j = 0,
lenJ = advancedLanguages.length;
let result = [];
while (i < len || j < lenJ) {
if (i < len && j < lenJ) {
if (basicLanguages[i].label === advancedLanguages[j].label) {
let entry = [];
entry.push(basicLanguages[i].entry);
entry.push(advancedLanguages[j].entry);
result.push({
label: basicLanguages[i].label,
entry: entry,
worker: advancedLanguages[j].worker
});
i++;
j++;
} else if (basicLanguages[i].label < advancedLanguages[j].label) {
result.push(basicLanguages[i]);
i++;
} else {
result.push(advancedLanguages[j]);
j++;
}
} else if (i < len) {
result.push(basicLanguages[i]);
i++;
} else {
result.push(advancedLanguages[j]);
j++;
}
}
const code = `//
// THIS IS A GENERATED FILE. PLEASE DO NOT EDIT DIRECTLY.
// GENERATED USING node scripts/import-editor.js
//
import { IFeatureDefinition } from "./types";
export const languagesArr: IFeatureDefinition[] = ${JSON.stringify(result, null, ' ')
.replace(/"label":/g, 'label:')
.replace(/"entry":/g, 'entry:')
.replace(/"worker":/g, 'worker:')
.replace(/"id":/g, 'id:')
.replace(/"/g, "'")};
export type EditorLanguage = ${result.map((el) => `'${el.label}'`).join(' | ')};
`;
fs.writeFileSync(path.join(__dirname, '../src/languages.ts'), code.replace(/\r\n/g, '\n'));
const readmeLanguages = JSON.stringify(result.map((r) => r.label))
.replace(/"/g, "'")
.replace(/','/g, "', '");
let readme = fs.readFileSync(path.join(__dirname, '../README.md')).toString();
readme = readme.replace(
/<!-- LANGUAGES_BEGIN -->([^<]+)<!-- LANGUAGES_END -->/,
`<!-- LANGUAGES_BEGIN -->\`${readmeLanguages}\`<!-- LANGUAGES_END -->`
);
fs.writeFileSync(path.join(__dirname, '../README.md'), readme);
}
);
}
function strcmp(a, b) {
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}
/**
* @returns { string[] }
*/
function generateFeatures() {
const skipImports = [
'vs/editor/browser/widget/codeEditorWidget',
'vs/editor/browser/widget/diffEditorWidget',
'vs/editor/browser/widget/diffNavigator',
'vs/editor/common/standaloneStrings',
'vs/editor/contrib/tokenization/tokenization',
'vs/editor/editor.all',
'vs/base/browser/ui/codicons/codiconStyles',
'vs/editor/contrib/gotoSymbol/documentSymbols'
];
let features = [];
const files =
fs
.readFileSync(
path.join(__dirname, '../node_modules/monaco-editor/esm/vs/editor/edcore.main.js')
)
.toString() +
fs
.readFileSync(
path.join(__dirname, '../node_modules/monaco-editor/esm/vs/editor/editor.all.js')
)
.toString();
files.split(/\r\n|\n/).forEach((line) => {
const m = line.match(/import '([^']+)'/);
if (m) {
const tmp = path.posix.join('vs/editor', m[1]).replace(/\.js$/, '');
if (skipImports.indexOf(tmp) === -1) {
features.push(tmp);
}
}
});
let result = features.map((feature) => {
return {
label: customFeatureLabels[feature] || path.basename(path.dirname(feature)),
entry: feature
};
});
result.sort((a, b) => {
const labelCmp = strcmp(a.label, b.label);
if (labelCmp === 0) {
return strcmp(a.entry, b.entry);
}
return labelCmp;
});
for (let i = 0; i < result.length; i++) {
if (i + 1 < result.length && result[i].label === result[i + 1].label) {
if (typeof result[i].entry === 'string') {
result[i].entry = [result[i].entry];
}
result[i].entry.push(result[i + 1].entry);
result.splice(i + 1, 1);
}
}
const code = `//
// THIS IS A GENERATED FILE. PLEASE DO NOT EDIT DIRECTLY.
// GENERATED USING node scripts/import-editor.js
//
import { IFeatureDefinition } from "./types";
export const featuresArr: IFeatureDefinition[] = ${JSON.stringify(result, null, ' ')
.replace(/"label":/g, 'label:')
.replace(/"entry":/g, 'entry:')
.replace(/"/g, "'")};
export type EditorFeature = ${result.map((el) => `'${el.label}'`).join(' | ')};
export type NegatedEditorFeature = ${result.map((el) => `'!${el.label}'`).join(' | ')};
`;
fs.writeFileSync(path.join(__dirname, '../src/features.ts'), code.replace(/\r\n/g, '\n'));
const readmeFeatures = JSON.stringify(result.map((r) => r.label))
.replace(/"/g, "'")
.replace(/','/g, "', '");
let readme = fs.readFileSync(path.join(__dirname, '../README.md')).toString();
readme = readme.replace(
/<!-- FEATURES_BEGIN -->([^<]+)<!-- FEATURES_END -->/,
`<!-- FEATURES_BEGIN -->\`${readmeFeatures}\`<!-- FEATURES_END -->`
);
fs.writeFileSync(path.join(__dirname, '../README.md'), readme);
}

View file

@ -0,0 +1,309 @@
//
// THIS IS A GENERATED FILE. PLEASE DO NOT EDIT DIRECTLY.
// GENERATED USING node scripts/import-editor.js
//
import { IFeatureDefinition } from './types';
export const featuresArr: IFeatureDefinition[] = [
{
label: 'accessibilityHelp',
entry: 'vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp'
},
{
label: 'anchorSelect',
entry: 'vs/editor/contrib/anchorSelect/anchorSelect'
},
{
label: 'bracketMatching',
entry: 'vs/editor/contrib/bracketMatching/bracketMatching'
},
{
label: 'caretOperations',
entry: 'vs/editor/contrib/caretOperations/caretOperations'
},
{
label: 'clipboard',
entry: 'vs/editor/contrib/clipboard/clipboard'
},
{
label: 'codeAction',
entry: 'vs/editor/contrib/codeAction/codeActionContributions'
},
{
label: 'codelens',
entry: 'vs/editor/contrib/codelens/codelensController'
},
{
label: 'colorPicker',
entry: 'vs/editor/contrib/colorPicker/colorContributions'
},
{
label: 'comment',
entry: 'vs/editor/contrib/comment/comment'
},
{
label: 'contextmenu',
entry: 'vs/editor/contrib/contextmenu/contextmenu'
},
{
label: 'coreCommands',
entry: 'vs/editor/browser/controller/coreCommands'
},
{
label: 'cursorUndo',
entry: 'vs/editor/contrib/cursorUndo/cursorUndo'
},
{
label: 'dnd',
entry: 'vs/editor/contrib/dnd/dnd'
},
{
label: 'documentSymbols',
entry: 'vs/editor/contrib/documentSymbols/documentSymbols'
},
{
label: 'find',
entry: 'vs/editor/contrib/find/findController'
},
{
label: 'folding',
entry: 'vs/editor/contrib/folding/folding'
},
{
label: 'fontZoom',
entry: 'vs/editor/contrib/fontZoom/fontZoom'
},
{
label: 'format',
entry: 'vs/editor/contrib/format/formatActions'
},
{
label: 'gotoError',
entry: 'vs/editor/contrib/gotoError/gotoError'
},
{
label: 'gotoLine',
entry: 'vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess'
},
{
label: 'gotoSymbol',
entry: [
'vs/editor/contrib/gotoSymbol/goToCommands',
'vs/editor/contrib/gotoSymbol/link/goToDefinitionAtPosition'
]
},
{
label: 'hover',
entry: 'vs/editor/contrib/hover/hover'
},
{
label: 'iPadShowKeyboard',
entry: 'vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard'
},
{
label: 'inPlaceReplace',
entry: 'vs/editor/contrib/inPlaceReplace/inPlaceReplace'
},
{
label: 'indentation',
entry: 'vs/editor/contrib/indentation/indentation'
},
{
label: 'inlayHints',
entry: 'vs/editor/contrib/inlayHints/inlayHintsController'
},
{
label: 'inlineCompletions',
entry: 'vs/editor/contrib/inlineCompletions/ghostTextController'
},
{
label: 'inspectTokens',
entry: 'vs/editor/standalone/browser/inspectTokens/inspectTokens'
},
{
label: 'linesOperations',
entry: 'vs/editor/contrib/linesOperations/linesOperations'
},
{
label: 'linkedEditing',
entry: 'vs/editor/contrib/linkedEditing/linkedEditing'
},
{
label: 'links',
entry: 'vs/editor/contrib/links/links'
},
{
label: 'multicursor',
entry: 'vs/editor/contrib/multicursor/multicursor'
},
{
label: 'parameterHints',
entry: 'vs/editor/contrib/parameterHints/parameterHints'
},
{
label: 'quickCommand',
entry: 'vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess'
},
{
label: 'quickHelp',
entry: 'vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess'
},
{
label: 'quickOutline',
entry: 'vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess'
},
{
label: 'referenceSearch',
entry: 'vs/editor/standalone/browser/referenceSearch/standaloneReferenceSearch'
},
{
label: 'rename',
entry: 'vs/editor/contrib/rename/rename'
},
{
label: 'smartSelect',
entry: 'vs/editor/contrib/smartSelect/smartSelect'
},
{
label: 'snippets',
entry: 'vs/editor/contrib/snippet/snippetController2'
},
{
label: 'suggest',
entry: 'vs/editor/contrib/suggest/suggestController'
},
{
label: 'toggleHighContrast',
entry: 'vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast'
},
{
label: 'toggleTabFocusMode',
entry: 'vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode'
},
{
label: 'transpose',
entry: 'vs/editor/contrib/caretOperations/transpose'
},
{
label: 'unusualLineTerminators',
entry: 'vs/editor/contrib/unusualLineTerminators/unusualLineTerminators'
},
{
label: 'viewportSemanticTokens',
entry: 'vs/editor/contrib/viewportSemanticTokens/viewportSemanticTokens'
},
{
label: 'wordHighlighter',
entry: 'vs/editor/contrib/wordHighlighter/wordHighlighter'
},
{
label: 'wordOperations',
entry: 'vs/editor/contrib/wordOperations/wordOperations'
},
{
label: 'wordPartOperations',
entry: 'vs/editor/contrib/wordPartOperations/wordPartOperations'
}
];
export type EditorFeature =
| 'accessibilityHelp'
| 'anchorSelect'
| 'bracketMatching'
| 'caretOperations'
| 'clipboard'
| 'codeAction'
| 'codelens'
| 'colorPicker'
| 'comment'
| 'contextmenu'
| 'coreCommands'
| 'cursorUndo'
| 'dnd'
| 'documentSymbols'
| 'find'
| 'folding'
| 'fontZoom'
| 'format'
| 'gotoError'
| 'gotoLine'
| 'gotoSymbol'
| 'hover'
| 'iPadShowKeyboard'
| 'inPlaceReplace'
| 'indentation'
| 'inlayHints'
| 'inlineCompletions'
| 'inspectTokens'
| 'linesOperations'
| 'linkedEditing'
| 'links'
| 'multicursor'
| 'parameterHints'
| 'quickCommand'
| 'quickHelp'
| 'quickOutline'
| 'referenceSearch'
| 'rename'
| 'smartSelect'
| 'snippets'
| 'suggest'
| 'toggleHighContrast'
| 'toggleTabFocusMode'
| 'transpose'
| 'unusualLineTerminators'
| 'viewportSemanticTokens'
| 'wordHighlighter'
| 'wordOperations'
| 'wordPartOperations';
export type NegatedEditorFeature =
| '!accessibilityHelp'
| '!anchorSelect'
| '!bracketMatching'
| '!caretOperations'
| '!clipboard'
| '!codeAction'
| '!codelens'
| '!colorPicker'
| '!comment'
| '!contextmenu'
| '!coreCommands'
| '!cursorUndo'
| '!dnd'
| '!documentSymbols'
| '!find'
| '!folding'
| '!fontZoom'
| '!format'
| '!gotoError'
| '!gotoLine'
| '!gotoSymbol'
| '!hover'
| '!iPadShowKeyboard'
| '!inPlaceReplace'
| '!indentation'
| '!inlayHints'
| '!inlineCompletions'
| '!inspectTokens'
| '!linesOperations'
| '!linkedEditing'
| '!links'
| '!multicursor'
| '!parameterHints'
| '!quickCommand'
| '!quickHelp'
| '!quickOutline'
| '!referenceSearch'
| '!rename'
| '!smartSelect'
| '!snippets'
| '!suggest'
| '!toggleHighContrast'
| '!toggleTabFocusMode'
| '!transpose'
| '!unusualLineTerminators'
| '!viewportSemanticTokens'
| '!wordHighlighter'
| '!wordOperations'
| '!wordPartOperations';

343
webpack-plugin/src/index.ts Normal file
View file

@ -0,0 +1,343 @@
import type * as webpack from 'webpack';
import * as path from 'path';
import * as loaderUtils from 'loader-utils';
import * as fs from 'fs';
import { AddWorkerEntryPointPlugin } from './plugins/AddWorkerEntryPointPlugin';
import { languagesArr, EditorLanguage } from './languages';
import { featuresArr, EditorFeature, NegatedEditorFeature } from './features';
import { IFeatureDefinition } from './types';
const INCLUDE_LOADER_PATH = require.resolve('./loaders/include');
const EDITOR_MODULE: IFeatureDefinition = {
label: 'editorWorkerService',
entry: undefined,
worker: {
id: 'vs/editor/editor',
entry: 'vs/editor/editor.worker'
}
};
const languagesById: { [language: string]: IFeatureDefinition } = {};
languagesArr.forEach((language) => (languagesById[language.label] = language));
const featuresById: { [feature: string]: IFeatureDefinition } = {};
featuresArr.forEach((feature) => (featuresById[feature.label] = feature));
/**
* Return a resolved path for a given Monaco file.
*/
function resolveMonacoPath(filePath: string, monacoEditorPath: string | undefined): string {
if (monacoEditorPath) {
return require.resolve(path.join(monacoEditorPath, 'esm', filePath));
}
try {
return require.resolve(path.join('monaco-editor/esm', filePath));
} catch (err) {}
try {
return require.resolve(path.join(process.cwd(), 'node_modules/monaco-editor/esm', filePath));
} catch (err) {}
return require.resolve(filePath);
}
/**
* Return the interpolated final filename for a worker, respecting the file name template.
*/
function getWorkerFilename(
filename: string,
entry: string,
monacoEditorPath: string | undefined
): string {
return loaderUtils.interpolateName(<any>{ resourcePath: entry }, filename, {
content: fs.readFileSync(resolveMonacoPath(entry, monacoEditorPath))
});
}
function getFeaturesIds(userFeatures: string[]): string[] {
function notContainedIn(arr: string[]) {
return (element: string) => arr.indexOf(element) === -1;
}
let featuresIds: string[];
if (userFeatures.length) {
const excludedFeatures = userFeatures.filter((f) => f[0] === '!').map((f) => f.slice(1));
if (excludedFeatures.length) {
featuresIds = Object.keys(featuresById).filter(notContainedIn(excludedFeatures));
} else {
featuresIds = userFeatures;
}
} else {
featuresIds = Object.keys(featuresById);
}
return featuresIds;
}
interface IMonacoEditorWebpackPluginOpts {
/**
* Include only a subset of the languages supported.
*/
languages?: EditorLanguage[];
/**
* Custom languages (outside of the ones shipped with the `monaco-editor`).
*/
customLanguages?: IFeatureDefinition[];
/**
* Include only a subset of the editor features.
* Use e.g. '!contextmenu' to exclude a certain feature.
*/
features?: (EditorFeature | NegatedEditorFeature)[];
/**
* Specify a filename template to use for generated files.
* Use e.g. '[name].worker.[contenthash].js' to include content-based hashes.
*/
filename?: string;
/**
* The absolute file system path to the monaco-editor npm module.
* Use e.g. `C:\projects\my-project\node-modules\monaco-editor`
*/
monacoEditorPath?: string;
/**
* Override the public path from which files generated by this plugin will be served.
* This wins out over Webpack's dynamic runtime path and can be useful to avoid attempting to load workers cross-
* origin when using a CDN for other static resources.
* Use e.g. '/' if you want to load your resources from the current origin.
*/
publicPath?: string;
/**
* Specify whether the editor API should be exposed through a global `monaco` object or not. This
* option is applicable to `0.22.0` and newer version of `monaco-editor`. Since `0.22.0`, the ESM
* version of the monaco editor does no longer define a global `monaco` object unless
* `global.MonacoEnvironment = { globalAPI: true }` is set ([change
* log](https://github.com/microsoft/monaco-editor/blob/main/CHANGELOG.md#0220-29012021)).
*/
globalAPI?: boolean;
}
interface IInternalMonacoEditorWebpackPluginOpts {
languages: IFeatureDefinition[];
features: IFeatureDefinition[];
filename: string;
monacoEditorPath: string | undefined;
publicPath: string;
globalAPI: boolean;
}
class MonacoEditorWebpackPlugin implements webpack.WebpackPluginInstance {
private readonly options: IInternalMonacoEditorWebpackPluginOpts;
constructor(options: IMonacoEditorWebpackPluginOpts = {}) {
const languages = options.languages || Object.keys(languagesById);
const customLanguages = options.customLanguages || [];
const features = getFeaturesIds(options.features || []);
this.options = {
languages: coalesce(languages.map((id) => languagesById[id])).concat(customLanguages),
features: coalesce(features.map((id) => featuresById[id])),
filename: options.filename || '[name].worker.js',
monacoEditorPath: options.monacoEditorPath,
publicPath: options.publicPath || '',
globalAPI: options.globalAPI || false
};
}
apply(compiler: webpack.Compiler): void {
const { languages, features, filename, monacoEditorPath, publicPath, globalAPI } = this.options;
const compilationPublicPath = getCompilationPublicPath(compiler);
const modules = [EDITOR_MODULE].concat(languages).concat(features);
const workers: ILabeledWorkerDefinition[] = [];
modules.forEach((module) => {
if (module.worker) {
workers.push({
label: module.label,
id: module.worker.id,
entry: module.worker.entry
});
}
});
const rules = createLoaderRules(
languages,
features,
workers,
filename,
monacoEditorPath,
publicPath,
compilationPublicPath,
globalAPI
);
const plugins = createPlugins(compiler, workers, filename, monacoEditorPath);
addCompilerRules(compiler, rules);
addCompilerPlugins(compiler, plugins);
}
}
interface ILabeledWorkerDefinition {
label: string;
id: string;
entry: string;
}
function addCompilerRules(compiler: webpack.Compiler, rules: webpack.RuleSetRule[]): void {
const compilerOptions = compiler.options;
if (!compilerOptions.module) {
compilerOptions.module = <any>{ rules: rules };
} else {
const moduleOptions = compilerOptions.module;
moduleOptions.rules = (moduleOptions.rules || []).concat(rules);
}
}
function addCompilerPlugins(compiler: webpack.Compiler, plugins: webpack.WebpackPluginInstance[]) {
plugins.forEach((plugin) => plugin.apply(compiler));
}
function getCompilationPublicPath(compiler: webpack.Compiler): string {
if (compiler.options.output && compiler.options.output.publicPath) {
if (typeof compiler.options.output.publicPath === 'string') {
return compiler.options.output.publicPath;
} else {
console.warn(`Cannot handle options.publicPath (expected a string)`);
}
}
return '';
}
function createLoaderRules(
languages: IFeatureDefinition[],
features: IFeatureDefinition[],
workers: ILabeledWorkerDefinition[],
filename: string,
monacoEditorPath: string | undefined,
pluginPublicPath: string,
compilationPublicPath: string,
globalAPI: boolean
): webpack.RuleSetRule[] {
if (!languages.length && !features.length) {
return [];
}
const languagePaths = flatArr(coalesce(languages.map((language) => language.entry)));
const featurePaths = flatArr(coalesce(features.map((feature) => feature.entry)));
const workerPaths = fromPairs(
workers.map(({ label, entry }) => [label, getWorkerFilename(filename, entry, monacoEditorPath)])
);
if (workerPaths['typescript']) {
// javascript shares the same worker
workerPaths['javascript'] = workerPaths['typescript'];
}
if (workerPaths['css']) {
// scss and less share the same worker
workerPaths['less'] = workerPaths['css'];
workerPaths['scss'] = workerPaths['css'];
}
if (workerPaths['html']) {
// handlebars, razor and html share the same worker
workerPaths['handlebars'] = workerPaths['html'];
workerPaths['razor'] = workerPaths['html'];
}
// Determine the public path from which to load worker JS files. In order of precedence:
// 1. Plugin-specific public path.
// 2. Dynamic runtime public path.
// 3. Compilation public path.
const pathPrefix = Boolean(pluginPublicPath)
? JSON.stringify(pluginPublicPath)
: `typeof __webpack_public_path__ === 'string' ` +
`? __webpack_public_path__ ` +
`: ${JSON.stringify(compilationPublicPath)}`;
const globals = {
MonacoEnvironment: `(function (paths) {
function stripTrailingSlash(str) {
return str.replace(/\\/$/, '');
}
return {
globalAPI: ${globalAPI},
getWorkerUrl: function (moduleId, label) {
var pathPrefix = ${pathPrefix};
var result = (pathPrefix ? stripTrailingSlash(pathPrefix) + '/' : '') + paths[label];
if (/^((http:)|(https:)|(file:)|(\\/\\/))/.test(result)) {
var currentUrl = String(window.location);
var currentOrigin = currentUrl.substr(0, currentUrl.length - window.location.hash.length - window.location.search.length - window.location.pathname.length);
if (result.substring(0, currentOrigin.length) !== currentOrigin) {
if(/^(\\/\\/)/.test(result)) {
result = window.location.protocol + result
}
var js = '/*' + label + '*/importScripts("' + result + '");';
var blob = new Blob([js], { type: 'application/javascript' });
return URL.createObjectURL(blob);
}
}
return result;
}
};
})(${JSON.stringify(workerPaths, null, 2)})`
};
return [
{
test: /esm[/\\]vs[/\\]editor[/\\]editor.(api|main).js/,
use: [
{
loader: INCLUDE_LOADER_PATH,
options: {
globals,
pre: featurePaths.map((importPath) => resolveMonacoPath(importPath, monacoEditorPath)),
post: languagePaths.map((importPath) => resolveMonacoPath(importPath, monacoEditorPath))
}
}
]
}
];
}
function createPlugins(
compiler: webpack.Compiler,
workers: ILabeledWorkerDefinition[],
filename: string,
monacoEditorPath: string | undefined
): AddWorkerEntryPointPlugin[] {
const webpack = compiler.webpack ?? require('webpack');
return (<AddWorkerEntryPointPlugin[]>[]).concat(
workers.map(
({ id, entry }) =>
new AddWorkerEntryPointPlugin({
id,
entry: resolveMonacoPath(entry, monacoEditorPath),
filename: getWorkerFilename(filename, entry, monacoEditorPath),
plugins: [new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 })]
})
)
);
}
function flatArr<T>(items: (T | T[])[]): T[] {
return items.reduce((acc: T[], item: T | T[]) => {
if (Array.isArray(item)) {
return (<T[]>[]).concat(acc).concat(item);
}
return (<T[]>[]).concat(acc).concat([item]);
}, <T[]>[]);
}
function fromPairs<T>(values: [string, T][]): { [key: string]: T } {
return values.reduce(
(acc, [key, value]) => Object.assign(acc, { [key]: value }),
<{ [key: string]: T }>{}
);
}
function coalesce<T>(array: ReadonlyArray<T | undefined | null>): T[] {
return <T[]>array.filter(Boolean);
}
export = MonacoEditorWebpackPlugin;

View file

@ -0,0 +1,414 @@
//
// THIS IS A GENERATED FILE. PLEASE DO NOT EDIT DIRECTLY.
// GENERATED USING node scripts/import-editor.js
//
import { IFeatureDefinition } from './types';
export const languagesArr: IFeatureDefinition[] = [
{
label: 'abap',
entry: 'vs/basic-languages/abap/abap.contribution'
},
{
label: 'apex',
entry: 'vs/basic-languages/apex/apex.contribution'
},
{
label: 'azcli',
entry: 'vs/basic-languages/azcli/azcli.contribution'
},
{
label: 'bat',
entry: 'vs/basic-languages/bat/bat.contribution'
},
{
label: 'bicep',
entry: 'vs/basic-languages/bicep/bicep.contribution'
},
{
label: 'cameligo',
entry: 'vs/basic-languages/cameligo/cameligo.contribution'
},
{
label: 'clojure',
entry: 'vs/basic-languages/clojure/clojure.contribution'
},
{
label: 'coffee',
entry: 'vs/basic-languages/coffee/coffee.contribution'
},
{
label: 'cpp',
entry: 'vs/basic-languages/cpp/cpp.contribution'
},
{
label: 'csharp',
entry: 'vs/basic-languages/csharp/csharp.contribution'
},
{
label: 'csp',
entry: 'vs/basic-languages/csp/csp.contribution'
},
{
label: 'css',
entry: ['vs/basic-languages/css/css.contribution', 'vs/language/css/monaco.contribution'],
worker: {
id: 'vs/language/css/cssWorker',
entry: 'vs/language/css/css.worker'
}
},
{
label: 'dart',
entry: 'vs/basic-languages/dart/dart.contribution'
},
{
label: 'dockerfile',
entry: 'vs/basic-languages/dockerfile/dockerfile.contribution'
},
{
label: 'ecl',
entry: 'vs/basic-languages/ecl/ecl.contribution'
},
{
label: 'elixir',
entry: 'vs/basic-languages/elixir/elixir.contribution'
},
{
label: 'flow9',
entry: 'vs/basic-languages/flow9/flow9.contribution'
},
{
label: 'fsharp',
entry: 'vs/basic-languages/fsharp/fsharp.contribution'
},
{
label: 'go',
entry: 'vs/basic-languages/go/go.contribution'
},
{
label: 'graphql',
entry: 'vs/basic-languages/graphql/graphql.contribution'
},
{
label: 'handlebars',
entry: 'vs/basic-languages/handlebars/handlebars.contribution'
},
{
label: 'hcl',
entry: 'vs/basic-languages/hcl/hcl.contribution'
},
{
label: 'html',
entry: ['vs/basic-languages/html/html.contribution', 'vs/language/html/monaco.contribution'],
worker: {
id: 'vs/language/html/htmlWorker',
entry: 'vs/language/html/html.worker'
}
},
{
label: 'ini',
entry: 'vs/basic-languages/ini/ini.contribution'
},
{
label: 'java',
entry: 'vs/basic-languages/java/java.contribution'
},
{
label: 'javascript',
entry: 'vs/basic-languages/javascript/javascript.contribution'
},
{
label: 'json',
entry: 'vs/language/json/monaco.contribution',
worker: {
id: 'vs/language/json/jsonWorker',
entry: 'vs/language/json/json.worker'
}
},
{
label: 'julia',
entry: 'vs/basic-languages/julia/julia.contribution'
},
{
label: 'kotlin',
entry: 'vs/basic-languages/kotlin/kotlin.contribution'
},
{
label: 'less',
entry: 'vs/basic-languages/less/less.contribution'
},
{
label: 'lexon',
entry: 'vs/basic-languages/lexon/lexon.contribution'
},
{
label: 'liquid',
entry: 'vs/basic-languages/liquid/liquid.contribution'
},
{
label: 'lua',
entry: 'vs/basic-languages/lua/lua.contribution'
},
{
label: 'm3',
entry: 'vs/basic-languages/m3/m3.contribution'
},
{
label: 'markdown',
entry: 'vs/basic-languages/markdown/markdown.contribution'
},
{
label: 'mips',
entry: 'vs/basic-languages/mips/mips.contribution'
},
{
label: 'msdax',
entry: 'vs/basic-languages/msdax/msdax.contribution'
},
{
label: 'mysql',
entry: 'vs/basic-languages/mysql/mysql.contribution'
},
{
label: 'objective-c',
entry: 'vs/basic-languages/objective-c/objective-c.contribution'
},
{
label: 'pascal',
entry: 'vs/basic-languages/pascal/pascal.contribution'
},
{
label: 'pascaligo',
entry: 'vs/basic-languages/pascaligo/pascaligo.contribution'
},
{
label: 'perl',
entry: 'vs/basic-languages/perl/perl.contribution'
},
{
label: 'pgsql',
entry: 'vs/basic-languages/pgsql/pgsql.contribution'
},
{
label: 'php',
entry: 'vs/basic-languages/php/php.contribution'
},
{
label: 'pla',
entry: 'vs/basic-languages/pla/pla.contribution'
},
{
label: 'postiats',
entry: 'vs/basic-languages/postiats/postiats.contribution'
},
{
label: 'powerquery',
entry: 'vs/basic-languages/powerquery/powerquery.contribution'
},
{
label: 'powershell',
entry: 'vs/basic-languages/powershell/powershell.contribution'
},
{
label: 'protobuf',
entry: 'vs/basic-languages/protobuf/protobuf.contribution'
},
{
label: 'pug',
entry: 'vs/basic-languages/pug/pug.contribution'
},
{
label: 'python',
entry: 'vs/basic-languages/python/python.contribution'
},
{
label: 'qsharp',
entry: 'vs/basic-languages/qsharp/qsharp.contribution'
},
{
label: 'r',
entry: 'vs/basic-languages/r/r.contribution'
},
{
label: 'razor',
entry: 'vs/basic-languages/razor/razor.contribution'
},
{
label: 'redis',
entry: 'vs/basic-languages/redis/redis.contribution'
},
{
label: 'redshift',
entry: 'vs/basic-languages/redshift/redshift.contribution'
},
{
label: 'restructuredtext',
entry: 'vs/basic-languages/restructuredtext/restructuredtext.contribution'
},
{
label: 'ruby',
entry: 'vs/basic-languages/ruby/ruby.contribution'
},
{
label: 'rust',
entry: 'vs/basic-languages/rust/rust.contribution'
},
{
label: 'sb',
entry: 'vs/basic-languages/sb/sb.contribution'
},
{
label: 'scala',
entry: 'vs/basic-languages/scala/scala.contribution'
},
{
label: 'scheme',
entry: 'vs/basic-languages/scheme/scheme.contribution'
},
{
label: 'scss',
entry: 'vs/basic-languages/scss/scss.contribution'
},
{
label: 'shell',
entry: 'vs/basic-languages/shell/shell.contribution'
},
{
label: 'solidity',
entry: 'vs/basic-languages/solidity/solidity.contribution'
},
{
label: 'sophia',
entry: 'vs/basic-languages/sophia/sophia.contribution'
},
{
label: 'sparql',
entry: 'vs/basic-languages/sparql/sparql.contribution'
},
{
label: 'sql',
entry: 'vs/basic-languages/sql/sql.contribution'
},
{
label: 'st',
entry: 'vs/basic-languages/st/st.contribution'
},
{
label: 'swift',
entry: 'vs/basic-languages/swift/swift.contribution'
},
{
label: 'systemverilog',
entry: 'vs/basic-languages/systemverilog/systemverilog.contribution'
},
{
label: 'tcl',
entry: 'vs/basic-languages/tcl/tcl.contribution'
},
{
label: 'twig',
entry: 'vs/basic-languages/twig/twig.contribution'
},
{
label: 'typescript',
entry: [
'vs/basic-languages/typescript/typescript.contribution',
'vs/language/typescript/monaco.contribution'
],
worker: {
id: 'vs/language/typescript/tsWorker',
entry: 'vs/language/typescript/ts.worker'
}
},
{
label: 'vb',
entry: 'vs/basic-languages/vb/vb.contribution'
},
{
label: 'xml',
entry: 'vs/basic-languages/xml/xml.contribution'
},
{
label: 'yaml',
entry: 'vs/basic-languages/yaml/yaml.contribution'
}
];
export type EditorLanguage =
| 'abap'
| 'apex'
| 'azcli'
| 'bat'
| 'bicep'
| 'cameligo'
| 'clojure'
| 'coffee'
| 'cpp'
| 'csharp'
| 'csp'
| 'css'
| 'dart'
| 'dockerfile'
| 'ecl'
| 'elixir'
| 'flow9'
| 'fsharp'
| 'go'
| 'graphql'
| 'handlebars'
| 'hcl'
| 'html'
| 'ini'
| 'java'
| 'javascript'
| 'json'
| 'julia'
| 'kotlin'
| 'less'
| 'lexon'
| 'liquid'
| 'lua'
| 'm3'
| 'markdown'
| 'mips'
| 'msdax'
| 'mysql'
| 'objective-c'
| 'pascal'
| 'pascaligo'
| 'perl'
| 'pgsql'
| 'php'
| 'pla'
| 'postiats'
| 'powerquery'
| 'powershell'
| 'protobuf'
| 'pug'
| 'python'
| 'qsharp'
| 'r'
| 'razor'
| 'redis'
| 'redshift'
| 'restructuredtext'
| 'ruby'
| 'rust'
| 'sb'
| 'scala'
| 'scheme'
| 'scss'
| 'shell'
| 'solidity'
| 'sophia'
| 'sparql'
| 'sql'
| 'st'
| 'swift'
| 'systemverilog'
| 'tcl'
| 'twig'
| 'typescript'
| 'vb'
| 'xml'
| 'yaml';

3
webpack-plugin/src/loader-utils.d.ts vendored Normal file
View file

@ -0,0 +1,3 @@
declare module 'loader-utils' {
export function interpolateName(loaderContext: any, name: string, options?: any): string;
}

View file

@ -0,0 +1,21 @@
const loaderUtils = require('loader-utils');
export function pitch(this: any, remainingRequest: any) {
const { globals = undefined, pre = [], post = [] } = loaderUtils.getOptions(this) || {};
// HACK: NamedModulesPlugin overwrites existing modules when requesting the same module via
// different loaders, so we need to circumvent this by appending a suffix to make the name unique
// See https://github.com/webpack/webpack/issues/4613#issuecomment-325178346 for details
if (this._module && this._module.userRequest) {
this._module.userRequest = `include-loader!${this._module.userRequest}`;
}
return [
...(globals
? Object.keys(globals).map((key) => `self[${JSON.stringify(key)}] = ${globals[key]};`)
: []),
...pre.map((include: any) => `require(${loaderUtils.stringifyRequest(this, include)});`),
`module.exports = require(${loaderUtils.stringifyRequest(this, `!!${remainingRequest}`)});`,
...post.map((include: any) => `require(${loaderUtils.stringifyRequest(this, include)});`)
].join('\n');
}

View file

@ -0,0 +1,63 @@
import type * as webpack from 'webpack';
export interface IAddWorkerEntryPointPluginOptions {
id: string;
entry: string;
filename: string;
chunkFilename?: string;
plugins: webpack.WebpackPluginInstance[];
}
function getCompilerHook(
compiler: webpack.Compiler,
{ id, entry, filename, chunkFilename, plugins }: IAddWorkerEntryPointPluginOptions
) {
const webpack = compiler.webpack ?? require('webpack');
return function (
compilation: webpack.Compilation,
callback: (error?: Error | null | false) => void
) {
const outputOptions = {
filename,
chunkFilename,
publicPath: compilation.outputOptions.publicPath,
// HACK: globalObject is necessary to fix https://github.com/webpack/webpack/issues/6642
globalObject: 'this'
};
const childCompiler = compilation.createChildCompiler(id, outputOptions, [
new webpack.webworker.WebWorkerTemplatePlugin(),
new webpack.LoaderTargetPlugin('webworker')
]);
const SingleEntryPlugin = webpack.EntryPlugin ?? webpack.SingleEntryPlugin;
new SingleEntryPlugin(compiler.context, entry, 'main').apply(childCompiler);
plugins.forEach((plugin) => plugin.apply(childCompiler));
childCompiler.runAsChild((err?: Error) => callback(err));
};
}
export class AddWorkerEntryPointPlugin implements webpack.WebpackPluginInstance {
private readonly options: IAddWorkerEntryPointPluginOptions;
constructor({
id,
entry,
filename,
chunkFilename = undefined,
plugins
}: IAddWorkerEntryPointPluginOptions) {
this.options = { id, entry, filename, chunkFilename, plugins };
}
apply(compiler: webpack.Compiler) {
const webpack = compiler.webpack ?? require('webpack');
const compilerHook = getCompilerHook(compiler, this.options);
const majorVersion = webpack.version.split('.')[0];
if (parseInt(majorVersion) < 4) {
(<any>compiler).plugin('make', compilerHook);
} else {
compiler.hooks.make.tapAsync('AddWorkerEntryPointPlugin', compilerHook);
}
}
}

View file

@ -0,0 +1,10 @@
export interface IWorkerDefinition {
id: string;
entry: string;
}
export interface IFeatureDefinition {
label: string;
entry: string | string[] | undefined;
worker?: IWorkerDefinition;
}

13
webpack-plugin/test/dist/index.html vendored Normal file
View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="container" style="width: 800px; height: 600px; border: 1px solid #ccc"></div>
<script type="text/javascript" src="app.js"></script>
</body>
</html>

View file

@ -0,0 +1,6 @@
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
monaco.editor.create(document.getElementById('container'), {
value: 'console.log("Hello, world")',
language: 'javascript'
});

View file

@ -0,0 +1,37 @@
const MonacoWebpackPlugin = require('../out/index.js');
const path = require('path');
const ASSET_PATH = 'http://localhost:8088/monaco-editor-webpack-plugin/test/dist/';
module.exports = {
mode: 'development',
entry: './index.js',
context: __dirname,
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js',
publicPath: ASSET_PATH
},
resolve: {
alias: {
'monaco-editor': path.resolve(__dirname, '../../release')
}
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.ttf$/,
use: ['file-loader']
}
]
},
plugins: [
new MonacoWebpackPlugin({
monacoEditorPath: path.resolve(__dirname, '../../release')
})
]
};

View file

@ -0,0 +1,34 @@
const MonacoWebpackPlugin = require('../out/index.js');
const path = require('path');
module.exports = {
mode: 'development',
entry: './index.js',
context: __dirname,
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js'
},
resolve: {
alias: {
'monaco-editor': path.resolve(__dirname, '../../release')
}
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.ttf$/,
use: ['file-loader']
}
]
},
plugins: [
new MonacoWebpackPlugin({
monacoEditorPath: path.resolve(__dirname, '../../release')
})
]
};

View file

@ -0,0 +1,11 @@
{
"compilerOptions": {
"module": "commonjs",
"outDir": "out",
"target": "es6",
"declaration": true,
"strict": true
},
"include": ["src"],
"exclude": ["node_modules"]
}