Merge branch 'main' into fix-memory-leak-webpack-plugin

This commit is contained in:
dgaponov 2025-10-03 18:05:00 +03:00 committed by GitHub
commit c4ad5f60f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
78 changed files with 3918 additions and 5199 deletions

View file

@ -51,13 +51,18 @@ extends:
testPlatforms: [] testPlatforms: []
skipAPIScan: true # package build requires Linux skipAPIScan: true # package build requires Linux
buildSteps: buildSteps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
- script: sudo apt install -y libkrb5-dev - script: sudo apt install -y libkrb5-dev
displayName: Install libkrb5-dev displayName: Install libkrb5-dev
- script: npm ci - script: npm ci
displayName: Install NPM dependencies displayName: Install NPM dependencies
- script: yarn ts-node ./scripts/ci/monaco-editor-core-prepare nightly - script: yarn ts-node ./scripts/ci/build-monaco-editor-core-pkg nightly
env: env:
VSCODE_REF: ${{ parameters.vscodeRef }} VSCODE_REF: ${{ parameters.vscodeRef }}
PRERELEASE_VERSION: ${{ parameters.prereleaseVersion }} PRERELEASE_VERSION: ${{ parameters.prereleaseVersion }}
@ -75,10 +80,18 @@ extends:
testPlatforms: [] testPlatforms: []
skipAPIScan: true # package build requires Linux skipAPIScan: true # package build requires Linux
buildSteps: buildSteps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
- script: npm ci - script: npm ci
displayName: Install NPM dependencies displayName: Install NPM dependencies
- script: yarn ts-node ./scripts/ci/monaco-editor-prepare nightly - script: npx playwright install --with-deps
displayName: Install Playwright Dependencies
- script: yarn ts-node ./scripts/ci/build-monaco-editor-pkg nightly
env: env:
VSCODE_REF: ${{ parameters.vscodeRef }} VSCODE_REF: ${{ parameters.vscodeRef }}
PRERELEASE_VERSION: ${{ parameters.prereleaseVersion }} PRERELEASE_VERSION: ${{ parameters.prereleaseVersion }}

View file

@ -39,13 +39,18 @@ extends:
testPlatforms: [] testPlatforms: []
skipAPIScan: true # package build requires Linux skipAPIScan: true # package build requires Linux
buildSteps: buildSteps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
- script: sudo apt install -y libkrb5-dev - script: sudo apt install -y libkrb5-dev
displayName: Install libkrb5-dev displayName: Install libkrb5-dev
- script: npm ci - script: npm ci
displayName: Install NPM dependencies displayName: Install NPM dependencies
- script: yarn ts-node ./scripts/ci/monaco-editor-core-prepare stable - script: yarn ts-node ./scripts/ci/build-monaco-editor-core-pkg stable
displayName: Setup, Build & Test monaco-editor-core displayName: Setup, Build & Test monaco-editor-core
tag: latest tag: latest
@ -59,10 +64,18 @@ extends:
testPlatforms: [] testPlatforms: []
skipAPIScan: true # package build requires Linux skipAPIScan: true # package build requires Linux
buildSteps: buildSteps:
- task: NodeTool@0
inputs:
versionSource: fromFile
versionFilePath: .nvmrc
- script: npm ci - script: npm ci
displayName: Install NPM dependencies displayName: Install NPM dependencies
- script: yarn ts-node ./scripts/ci/monaco-editor-prepare stable - script: npx playwright install --with-deps
displayName: Install Playwright Dependencies
- script: yarn ts-node ./scripts/ci/build-monaco-editor-pkg stable
displayName: Setup, Build & Test monaco-editor displayName: Setup, Build & Test monaco-editor
tag: latest tag: latest

View file

@ -5,13 +5,15 @@ on: [push, pull_request]
jobs: jobs:
build: build:
name: CI name: CI
runs-on: ubuntu-22.04 runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561 # pin@v2
with: with:
node-version: 20 persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
- name: Cache node modules - name: Cache node modules
id: cacheNodeModules id: cacheNodeModules
@ -21,25 +23,49 @@ jobs:
key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('**/package-lock.json', '**/package.json') }} key: ${{ runner.os }}-cacheNodeModules2-${{ hashFiles('**/package-lock.json', '**/package.json') }}
restore-keys: ${{ runner.os }}-cacheNodeModules2- restore-keys: ${{ runner.os }}-cacheNodeModules2-
- name: Install build tools
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: |
sudo apt update -y
sudo apt install -y build-essential pkg-config libx11-dev libx11-xcb-dev libxkbfile-dev libnotify-bin libkrb5-dev
- name: execute `npm ci` (1) - name: execute `npm ci` (1)
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
run: npm ci env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
run: |
npm ci
- name: Download Playwright
run: npx playwright install --with-deps
- name: execute `npm ci` (2) - name: execute `npm ci` (2)
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
run: npm ci --prefix webpack-plugin run: npm ci --prefix webpack-plugin
- name: Install Playwright # CI steps temporarily disabled (enable by end of august 2025)
run: npm run playwright-install # # <building-from-source>
# - name: Setup, Build & Test monaco-editor-core
# run: yarn ts-node ./scripts/ci/build-monaco-editor-core-pkg nightly
# env:
# VSCODE_REF: 'main'
# PRERELEASE_VERSION: 'dev-${today}'
- name: Install OS Dependencies for Playwright # - name: Link monaco-editor-core
run: sudo npm run playwright-install-deps # run: npm link
# working-directory: ./dependencies/vscode/out-monaco-editor-core
- name: Check prettier # - name: Link monaco-editor-core
run: npm run prettier-check # run: npm link monaco-editor-core
# # </building-from-source>
# TODO: prettier formatting
# - name: Check prettier
# run: npm run prettier-check
- name: Build - name: Build
run: npm run build-monaco-editor run: npm run build
- name: Run unit tests - name: Run unit tests
run: npm test run: npm test
@ -63,14 +89,14 @@ jobs:
- name: Run smoke test - name: Run smoke test
run: npm run smoketest run: npm run smoketest
- name: Install website node modules # - name: Install website node modules
working-directory: website # working-directory: website
run: yarn install --frozen-lockfile # run: yarn install --frozen-lockfile
- name: Build website # - name: Build website
working-directory: website # working-directory: website
run: yarn run build # run: yarn run build
- name: Test website # - name: Test website
working-directory: website # working-directory: website
run: yarn test # run: yarn test

View file

@ -26,9 +26,9 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561 # pin@v2 - uses: actions/setup-node@v4
with: with:
node-version: 20 node-version-file: .nvmrc
- name: Cache node modules - name: Cache node modules
id: cacheNodeModules id: cacheNodeModules
uses: actions/cache@v4 uses: actions/cache@v4

2
.nvmrc
View file

@ -1 +1 @@
20.14.0 22.18.0

View file

@ -1,5 +1,21 @@
# Monaco Editor Changelog # Monaco Editor Changelog
## [0.53.0]
- :warning: This release deprecates the AMD build and ships with significant changes of the AMD build. The AMD build will still be shipped for a while, but we don't offer support for it anymore. Please migrate to the ESM build.
### New Features
- Next Edit Suggestion support.
- Scroll On Middle Click
- Edit Context Support
### Breaking Changes
- Internal AMD modules are no longer accessible. Accessing internal AMD modules was never supported. While this is still possible in the ESM build, we don't encourage this usage pattern.
- The [browser-script-editor scenario](https://github.com/microsoft/monaco-editor/blob/a4d7907bd439b06b24e334bdf2ab597bcae658b5/samples/browser-script-editor/index.html) for unbundled synchronous script import and editor creation no longer works. Instead, a the ESM build should be used with a bundler, such as vite or webpack.
- Custom AMD workers don't work anymore out of the box.
## [0.52.0] ## [0.52.0]
- Comment added inside of `IModelContentChangedEvent` - Comment added inside of `IModelContentChangedEvent`

View file

@ -24,12 +24,9 @@ The playground is the best way to learn about how to use the editor, which featu
You will get: You will get:
- inside `/esm`: ESM version of the editor (compatible with e.g. webpack) - inside `/esm`: ESM version of the editor (compatible with e.g. webpack)
- inside `/dev`: AMD bundled, not minified
- inside `/min`: AMD bundled, and minified
- inside `/min-maps`: source maps for `min`
- `monaco.d.ts`: this specifies the API of the editor (this is what is actually versioned, everything else is considered private and might break with any release). - `monaco.d.ts`: this specifies the API of the editor (this is what is actually versioned, everything else is considered private and might break with any release).
It is recommended to develop against the `dev` version, and in production to use the `min` version. :warning: The monaco editor also ships an `AMD` build for backwards-compatibility reasons, but the `AMD` support is deprecated and will be removed in future versions.
## Concepts ## Concepts
@ -60,7 +57,6 @@ Many Monaco related objects often implement the `.dispose()` method. This method
## Documentation ## Documentation
- Learn how to integrate the editor with these [complete samples](./samples/). - Learn how to integrate the editor with these [complete samples](./samples/).
- [Integrate the AMD version](./docs/integrate-amd.md).
- [Integrate the ESM version](./docs/integrate-esm.md) - [Integrate the ESM version](./docs/integrate-esm.md)
- Learn how to use the editor API and try out your own customizations in the [playground](https://microsoft.github.io/monaco-editor/playground.html). - Learn how to use the editor API and try out your own customizations in the [playground](https://microsoft.github.io/monaco-editor/playground.html).
- Explore the [API docs](https://microsoft.github.io/monaco-editor/docs.html) or read them straight from [`monaco.d.ts`](https://github.com/microsoft/monaco-editor/blob/gh-pages/node_modules/monaco-editor/monaco.d.ts). - Explore the [API docs](https://microsoft.github.io/monaco-editor/docs.html) or read them straight from [`monaco.d.ts`](https://github.com/microsoft/monaco-editor/blob/gh-pages/node_modules/monaco-editor/monaco.d.ts).
@ -92,10 +88,6 @@ No.
Language services create web workers to compute heavy stuff outside of the UI thread. They cost hardly anything in terms of resource overhead and you shouldn't worry too much about them, as long as you get them to work (see above the cross-domain case). Language services create web workers to compute heavy stuff outside of the UI thread. They cost hardly anything in terms of resource overhead and you shouldn't worry too much about them, as long as you get them to work (see above the cross-domain case).
❓ **What is this `loader.js`? Can I use `require.js`?**
It is an AMD loader that we use in VS Code. Yes.
❓ **I see the warning "Could not create web worker". What should I do?** ❓ **I see the warning "Could not create web worker". What should I do?**
HTML5 does not allow pages loaded on `file://` to create web workers. Please load the editor with a web server on `http://` or `https://` schemes. HTML5 does not allow pages loaded on `file://` to create web workers. Please load the editor with a web server on `http://` or `https://` schemes.

View file

@ -0,0 +1,7 @@
import { run } from '../../scripts/lib/index';
export async function buildAmdMinDev() {
const rootPath = __dirname;
await run('npx vite build --mode development', { cwd: rootPath });
await run('npx vite build', { cwd: rootPath });
}

60
build/amd/plugin.js Normal file
View file

@ -0,0 +1,60 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* @type {() => import('rollup').Plugin}
*/
export function urlToEsmPlugin() {
return {
name: 'import-meta-url',
async transform(code, id) {
if (this.environment?.mode === 'dev') {
return;
}
let idx = 0;
// Look for `new URL("...?worker", import.meta.url)` patterns.
const regex = /new\s+URL\s*\(\s*(['"`])(.*?)\?worker\1\s*,\s*import\.meta\.url\s*\)?/g;
let match;
let modified = false;
let result = code;
let offset = 0;
/** @type {string[]} */
const additionalImports = [];
while ((match = regex.exec(code)) !== null) {
let path = match[2];
if (!path.startsWith('.') && !path.startsWith('/')) {
path = `./${path}`;
}
const start = match.index;
const end = start + match[0].length;
const varName = `__worker_url_${idx++}__`;
additionalImports.push(`import ${varName} from ${JSON.stringify(path + '?worker&url')};`);
const replacement = varName;
result = result.slice(0, start + offset) + replacement + result.slice(end + offset);
offset += replacement.length - (end - start);
modified = true;
}
if (!modified) {
return null;
}
result = additionalImports.join('\n') + '\n' + result;
return {
code: result,
map: null
};
}
};
}

View file

@ -0,0 +1,70 @@
import * as require from 'require';
self.MonacoEnvironment = {
getWorker: function (_moduleId, label) {
if (label === 'json') {
return new Worker(
getWorkerBootstrapUrl(
new URL('../../../src/language/json/json.worker.ts?worker', import.meta.url)
)
);
}
if (label === 'css' || label === 'scss' || label === 'less') {
return new Worker(
getWorkerBootstrapUrl(
new URL('../../../src/language/css/css.worker.ts?worker', import.meta.url)
)
);
}
if (label === 'html' || label === 'handlebars' || label === 'razor') {
return new Worker(
getWorkerBootstrapUrl(
new URL('../../../src/language/html/html.worker.ts?worker', import.meta.url)
)
);
}
if (label === 'typescript' || label === 'javascript') {
return new Worker(
getWorkerBootstrapUrl(
new URL('../../../src/language/typescript/ts.worker.ts?worker', import.meta.url)
)
);
}
return new Worker(
getWorkerBootstrapUrl(new URL('../../../src/editor/editor.worker.ts?worker', import.meta.url))
);
}
};
function getWorkerBootstrapUrl(workerScriptUrl) {
const blob = new Blob(
[
[
`const ttPolicy = globalThis.trustedTypes?.createPolicy('defaultWorkerFactory', { createScriptURL: value => value });`,
`globalThis.workerttPolicy = ttPolicy;`,
`importScripts(ttPolicy?.createScriptURL(${JSON.stringify(
workerScriptUrl
)}) ?? ${JSON.stringify(workerScriptUrl)});`,
`globalThis.postMessage({ type: 'vscode-worker-ready' });`
].join('')
],
{ type: 'application/javascript' }
);
return URL.createObjectURL(blob);
}
import 'vs/nls.messages-loader!';
import '../../../src/basic-languages/monaco.contribution';
import '../../../src/language/css/monaco.contribution';
import '../../../src/language/html/monaco.contribution';
import '../../../src/language/json/monaco.contribution';
import '../../../src/language/typescript/monaco.contribution';
const styleSheetUrl = require.toUrl('vs/editor/editor.main.css');
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = styleSheetUrl;
document.head.appendChild(link);
export * as m from 'monaco-editor-core';

1368
build/amd/src/loader.js Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,10 @@
export function load(name, req, load, config) {
const requestedLanguage = config['vs/nls']?.availableLanguages?.['*'];
if (!requestedLanguage || requestedLanguage === 'en') {
load({});
} else {
req([`vs/nls.messages.${requestedLanguage}`], () => {
load({});
});
}
}

92
build/amd/vite.config.js Normal file
View file

@ -0,0 +1,92 @@
import { readFileSync } from 'node:fs';
import { glob } from 'node:fs/promises';
import { basename, dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { defineConfig } from 'vite';
import { urlToEsmPlugin } from './plugin';
const __dirname = dirname(fileURLToPath(import.meta.url));
export default defineConfig(async (args) => {
const monacoEditorCoreDir = join(
dirname(require.resolve('monaco-editor-core/package.json')),
'esm'
);
const nlsEntries = {};
for await (const path of glob(`${monacoEditorCoreDir}/nls.messages.*.js`)) {
const entryName = basename(path).replace('.js', '');
nlsEntries[entryName] = path;
}
/** @type {import('vite').UserConfig} */
return {
base: './',
define: {
AMD: false
},
build: {
lib: {
cssFileName: 'editor/editor.main',
entry: {
...nlsEntries,
'nls.messages-loader': resolve(__dirname, 'src/nls.messages-loader.js'),
'editor/editor.main': resolve(__dirname, 'src/editor.main.js'),
'basic-languages/monaco.contribution': resolve(
__dirname,
'../../src/basic-languages/monaco.contribution.ts'
),
'language/css/monaco.contribution': resolve(
__dirname,
'../../src/language/css/monaco.contribution.ts'
),
'language/html/monaco.contribution': resolve(
__dirname,
'../../src/language/html/monaco.contribution.ts'
),
'language/json/monaco.contribution': resolve(
__dirname,
'../../src/language/json/monaco.contribution.ts'
),
'language/typescript/monaco.contribution': resolve(
__dirname,
'../../src/language/typescript/monaco.contribution.ts'
)
},
name: 'monaco-editor',
fileName: (_format, entryName) => entryName + '.js',
formats: ['amd']
},
outDir: resolve(
__dirname,
'../../out/monaco-editor/',
args.mode === 'development' ? 'dev' : 'min',
'vs'
),
rollupOptions: {
external: ['require', 'vs/nls.messages-loader!'],
output: {
amd: {
basePath: 'vs',
autoId: true
}
}
},
minify: args.mode !== 'development',
emptyOutDir: true
},
plugins: [
{
name: 'copy-loader',
apply: 'build',
generateBundle() {
this.emitFile({
type: 'asset',
fileName: 'loader.js',
source: readFileSync(resolve(__dirname, './src/loader.js'), 'utf-8')
});
}
},
urlToEsmPlugin()
]
};
});

View file

@ -4,8 +4,8 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import glob from 'glob'; import glob from 'glob';
import { runTsc, massageAndCopyDts, buildESM, buildAMD } from './utils'; import { runTsc, massageAndCopyDts, buildESM } from './utils';
import { copyFile, removeDir } from './fs'; import { removeDir } from './fs';
removeDir(`out/languages`); removeDir(`out/languages`);
@ -14,22 +14,22 @@ runTsc(`src/tsconfig.json`);
//#region Type Defintion //#region Type Defintion
massageAndCopyDts( massageAndCopyDts(
`out/languages/amd-tsc/language/css/monaco.contribution.d.ts`, `out/languages/tsc/language/css/monaco.contribution.d.ts`,
`out/languages/bundled/css.d.ts`, `out/languages/bundled/css.d.ts`,
'monaco.languages.css' 'monaco.languages.css'
); );
massageAndCopyDts( massageAndCopyDts(
`out/languages/amd-tsc/language/html/monaco.contribution.d.ts`, `out/languages/tsc/language/html/monaco.contribution.d.ts`,
`out/languages/bundled/html.d.ts`, `out/languages/bundled/html.d.ts`,
'monaco.languages.html' 'monaco.languages.html'
); );
massageAndCopyDts( massageAndCopyDts(
`out/languages/amd-tsc/language/json/monaco.contribution.d.ts`, `out/languages/tsc/language/json/monaco.contribution.d.ts`,
`out/languages/bundled/json.d.ts`, `out/languages/bundled/json.d.ts`,
'monaco.languages.json' 'monaco.languages.json'
); );
massageAndCopyDts( massageAndCopyDts(
`out/languages/amd-tsc/language/typescript/monaco.contribution.d.ts`, `out/languages/tsc/language/typescript/monaco.contribution.d.ts`,
`out/languages/bundled/typescript.d.ts`, `out/languages/bundled/typescript.d.ts`,
'monaco.languages.typescript' 'monaco.languages.typescript'
); );
@ -47,23 +47,6 @@ buildESM({
], ],
external: ['monaco-editor-core', '*/cssMode', '*/monaco.contribution'] external: ['monaco-editor-core', '*/cssMode', '*/monaco.contribution']
}); });
buildAMD({
base: 'language/css',
entryPoint: 'src/language/css/monaco.contribution.ts',
amdModuleId: 'vs/language/css/monaco.contribution',
amdDependencies: ['vs/editor/editor.api']
});
buildAMD({
base: 'language/css',
entryPoint: 'src/language/css/cssMode.ts',
amdModuleId: 'vs/language/css/cssMode',
external: ['*/monaco.contribution']
});
buildAMD({
base: 'language/css',
entryPoint: 'src/language/css/cssWorker.ts',
amdModuleId: 'vs/language/css/cssWorker'
});
//#endregion //#endregion
@ -78,23 +61,6 @@ buildESM({
], ],
external: ['monaco-editor-core', '*/htmlMode', '*/monaco.contribution'] external: ['monaco-editor-core', '*/htmlMode', '*/monaco.contribution']
}); });
buildAMD({
base: 'language/html',
entryPoint: 'src/language/html/monaco.contribution.ts',
amdModuleId: 'vs/language/html/monaco.contribution',
amdDependencies: ['vs/editor/editor.api']
});
buildAMD({
base: 'language/html',
entryPoint: 'src/language/html/htmlMode.ts',
amdModuleId: 'vs/language/html/htmlMode',
external: ['*/monaco.contribution']
});
buildAMD({
base: 'language/html',
entryPoint: 'src/language/html/htmlWorker.ts',
amdModuleId: 'vs/language/html/htmlWorker'
});
//#endregion //#endregion
@ -109,23 +75,6 @@ buildESM({
], ],
external: ['monaco-editor-core', '*/jsonMode', '*/monaco.contribution'] external: ['monaco-editor-core', '*/jsonMode', '*/monaco.contribution']
}); });
buildAMD({
base: 'language/json',
entryPoint: 'src/language/json/monaco.contribution.ts',
amdModuleId: 'vs/language/json/monaco.contribution',
amdDependencies: ['vs/editor/editor.api']
});
buildAMD({
base: 'language/json',
entryPoint: 'src/language/json/jsonMode.ts',
amdModuleId: 'vs/language/json/jsonMode',
external: ['*/monaco.contribution']
});
buildAMD({
base: 'language/json',
entryPoint: 'src/language/json/jsonWorker.ts',
amdModuleId: 'vs/language/json/jsonWorker'
});
//#endregion //#endregion
@ -140,23 +89,6 @@ buildESM({
], ],
external: ['monaco-editor-core', '*/tsMode', '*/monaco.contribution'] external: ['monaco-editor-core', '*/tsMode', '*/monaco.contribution']
}); });
buildAMD({
base: 'language/typescript',
entryPoint: 'src/language/typescript/monaco.contribution.ts',
amdModuleId: 'vs/language/typescript/monaco.contribution',
amdDependencies: ['vs/editor/editor.api']
});
buildAMD({
base: 'language/typescript',
entryPoint: 'src/language/typescript/tsMode.ts',
amdModuleId: 'vs/language/typescript/tsMode',
external: ['*/monaco.contribution']
});
buildAMD({
base: 'language/typescript',
entryPoint: 'src/language/typescript/tsWorker.ts',
amdModuleId: 'vs/language/typescript/tsWorker'
});
//#endregion //#endregion
@ -190,23 +122,6 @@ glob('../src/basic-languages/*/*.contribution.ts', { cwd: __dirname }, function
external external
}); });
} }
// AMD
{
buildAMD({
base: 'basic-languages',
entryPoint: 'src/basic-languages/monaco.contribution.ts',
amdModuleId: 'vs/basic-languages/monaco.contribution',
amdDependencies: ['vs/editor/editor.api']
});
for (const language of languages) {
buildAMD({
base: 'basic-languages',
entryPoint: `src/basic-languages/${language}/${language}.ts`,
amdModuleId: `vs/basic-languages/${language}/${language}`
});
}
}
}); });
//#endregion //#endregion

View file

@ -5,18 +5,23 @@
import path = require('path'); import path = require('path');
import fs = require('fs'); import fs = require('fs');
import { REPO_ROOT, readFiles, writeFiles, IFile, readFile } from '../build/utils'; import {
REPO_ROOT,
readFiles,
writeFiles,
IFile,
readFile,
build,
bundledFileHeader
} from '../build/utils';
import { removeDir } from '../build/fs'; import { removeDir } from '../build/fs';
import ts = require('typescript');
import { generateMetadata } from './releaseMetadata'; import { generateMetadata } from './releaseMetadata';
import { buildAmdMinDev } from './amd/build.script';
import ts = require('typescript');
removeDir(`out/monaco-editor`); removeDir(`out/monaco-editor`);
// dev folder buildAmdMinDev();
AMD_releaseOne('dev');
// min folder
AMD_releaseOne('min');
// esm folder // esm folder
ESM_release(); ESM_release();
@ -48,11 +53,6 @@ generateMetadata();
otherFiles = otherFiles.concat(readFiles('README.md', { base: '' })); otherFiles = otherFiles.concat(readFiles('README.md', { base: '' }));
otherFiles = otherFiles.concat(readFiles('CHANGELOG.md', { base: '' })); otherFiles = otherFiles.concat(readFiles('CHANGELOG.md', { base: '' }));
otherFiles = otherFiles.concat(
readFiles('node_modules/monaco-editor-core/min-maps/**/*', {
base: 'node_modules/monaco-editor-core/'
})
);
otherFiles = otherFiles.concat( otherFiles = otherFiles.concat(
readFiles('node_modules/monaco-editor-core/LICENSE', { readFiles('node_modules/monaco-editor-core/LICENSE', {
base: 'node_modules/monaco-editor-core/' base: 'node_modules/monaco-editor-core/'
@ -62,114 +62,6 @@ generateMetadata();
writeFiles(otherFiles, `out/monaco-editor`); writeFiles(otherFiles, `out/monaco-editor`);
})(); })();
/**
* Release to `dev` or `min`.
*/
function AMD_releaseOne(type: 'dev' | 'min') {
let coreFiles = readFiles(`node_modules/monaco-editor-core/${type}/**/*`, {
base: `node_modules/monaco-editor-core/${type}`
});
coreFiles = fixNlsFiles(coreFiles);
AMD_addPluginContribs(type, coreFiles);
writeFiles(coreFiles, `out/monaco-editor/${type}`);
const pluginFiles = readFiles(`out/languages/bundled/amd-${type}/**/*`, {
base: `out/languages/bundled/amd-${type}`,
ignore: ['**/monaco.contribution.js']
});
writeFiles(pluginFiles, `out/monaco-editor/${type}`);
}
function fixNlsFiles(files: IFile[]): IFile[] {
return files.map((f) => {
if (!f.path.match(/nls\.messages\.[a-z\-]+\.js/)) {
return f;
}
const dirName = path.dirname(f.path);
const fileName = path.basename(f.path);
const newPath = path.join(dirName, 'vs', fileName);
let contentStr = f.contents.toString('utf-8');
contentStr = `
define([], function () {
${contentStr}
});
`;
const newContents = Buffer.from(contentStr, 'utf-8');
return {
path: newPath,
contents: newContents
};
});
}
/**
* Edit editor.main.js:
* - rename the AMD module 'vs/editor/editor.main' to 'vs/editor/edcore.main'
* - append monaco.contribution modules from plugins
* - append new AMD module 'vs/editor/editor.main' that stiches things together
*/
function AMD_addPluginContribs(type: 'dev' | 'min', files: IFile[]) {
for (const file of files) {
if (!/editor\.main\.js$/.test(file.path)) {
continue;
}
let contents = file.contents.toString();
// Rename the AMD module 'vs/editor/editor.main' to 'vs/editor/edcore.main'
contents = contents.replace(/"vs\/editor\/editor\.main\"/, '"vs/editor/edcore.main"');
// This ensures that old nls-plugin configurations are still respected by the new localization solution.
const contentPrefixSource = readFile('src/nls-fix.js')
.contents.toString('utf-8')
.replace(/\r\n|\n/g, ' ');
// TODO: Instead of adding this source to the header to maintain the source map indices, it should rewrite the sourcemap!
const searchValue = 'https://github.com/microsoft/vscode/blob/main/LICENSE.txt';
contents = contents.replace(searchValue, searchValue + ' */ ' + contentPrefixSource + ' /*');
const pluginFiles = readFiles(`out/languages/bundled/amd-${type}/**/monaco.contribution.js`, {
base: `out/languages/bundled/amd-${type}`
});
const extraContent = pluginFiles.map((file) => {
return file.contents
.toString()
.replace(
/define\((['"][a-z\/\-]+\/fillers\/monaco-editor-core['"]),\[\],/,
"define($1,['vs/editor/editor.api'],"
);
});
const allPluginsModuleIds = pluginFiles.map((file) => {
return file.path.replace(/\.js$/, '');
});
extraContent.push(
`define("vs/editor/editor.main", ["vs/editor/edcore.main","${allPluginsModuleIds.join(
'","'
)}"], function(api) { return api; });`
);
let insertIndex = contents.lastIndexOf('//# sourceMappingURL=');
if (insertIndex === -1) {
insertIndex = contents.length;
}
contents =
contents.substring(0, insertIndex) +
'\n' +
extraContent.join('\n') +
'\n' +
contents.substring(insertIndex);
file.contents = Buffer.from(contents);
}
}
function ESM_release() { function ESM_release() {
const coreFiles = readFiles(`node_modules/monaco-editor-core/esm/**/*`, { const coreFiles = readFiles(`node_modules/monaco-editor-core/esm/**/*`, {
base: 'node_modules/monaco-editor-core/esm', base: 'node_modules/monaco-editor-core/esm',
@ -181,6 +73,40 @@ function ESM_release() {
writeFiles(coreFiles, `out/monaco-editor/esm`); writeFiles(coreFiles, `out/monaco-editor/esm`);
ESM_releasePlugins(); ESM_releasePlugins();
build({
entryPoints: ['src/editor/editor.main.ts', 'src/editor/editor.worker.ts'],
bundle: true,
target: 'esnext',
format: 'esm',
drop: ['debugger'],
define: {
AMD: 'false'
},
banner: {
js: bundledFileHeader
},
external: ['./src/basic-languages/*', './edcore.main.js', './editor.worker.start'],
alias: {
'monaco-editor-core/esm/vs/editor/editor.worker.start': './editor.worker.start',
'monaco-editor-core': './edcore.main.js'
},
outbase: `src/`,
outdir: `out/monaco-editor/esm/vs/`,
plugins: [
{
name: 'example',
setup(build) {
build.onResolve({ filter: /\/language\/|\/basic-languages\// }, (args) => {
if (args.path.includes('monaco-editor-core')) {
return undefined;
}
return { external: true };
});
}
}
]
});
} }
/** /**
@ -198,6 +124,7 @@ function ESM_releasePlugins() {
let contents = file.contents.toString(); let contents = file.contents.toString();
// WARNING: this only returns the first occurence of each imported file!
const info = ts.preProcessFile(contents); const info = ts.preProcessFile(contents);
for (let i = info.importedFiles.length - 1; i >= 0; i--) { for (let i = info.importedFiles.length - 1; i >= 0; i--) {
let importText = info.importedFiles[i].fileName; let importText = info.importedFiles[i].fileName;
@ -290,32 +217,6 @@ function ESM_addPluginContribs(files: IFile[]) {
} }
file.path = file.path.replace(/editor\.main/, 'edcore.main'); file.path = file.path.replace(/editor\.main/, 'edcore.main');
} }
const mainFileDestPath = 'vs/editor/editor.main.js';
const mainFileImports = readFiles(`out/languages/bundled/esm/**/monaco.contribution.js`, {
base: `out/languages/bundled/esm`
}).map((file) => {
let relativePath = path
.relative(path.dirname(mainFileDestPath), file.path)
.replace(/\\/g, '/')
.replace(/\.js$/, '');
if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) {
relativePath = './' + relativePath;
}
return relativePath;
});
const mainFileContents =
mainFileImports.map((name) => `import '${name}';`).join('\n') +
`\n\nexport * from './edcore.main';`;
files.push({
path: mainFileDestPath,
contents: Buffer.from(mainFileContents)
});
} }
/** /**
@ -329,6 +230,32 @@ function releaseDTS() {
let contents = monacodts.contents.toString(); let contents = monacodts.contents.toString();
const additionalDtsFiles: Record<string, string> = {
'out/languages/tsc/common/workers.d.ts': 'monaco.editor'
};
Object.entries(additionalDtsFiles).forEach(([filePath, namespace]) => {
try {
const dtsFile = readFile(filePath);
let dtsContent = dtsFile.contents.toString();
// Remove imports
dtsContent = dtsContent.replace(/import .*\n/gm, '');
dtsContent = dtsContent.replace(/export declare function/gm, 'export function');
// Wrap in namespace if specified
if (namespace) {
dtsContent = `declare namespace ${namespace} {\n${dtsContent
.split('\n')
.map((line) => (line ? ` ${line}` : line))
.join('\n')}\n}`;
}
contents += '\n' + dtsContent;
} catch (error) {
console.warn(`Could not read d.ts file: ${filePath}`);
}
});
const extraContent = readFiles('out/languages/bundled/*.d.ts', { const extraContent = readFiles('out/languages/bundled/*.d.ts', {
base: 'out/languages/bundled/' base: 'out/languages/bundled/'
}).map((file) => { }).map((file) => {
@ -366,12 +293,13 @@ function releaseDTS() {
/** /**
* Transforms a .d.ts which uses internal modules (namespaces) to one which is usable with external modules * Transforms a .d.ts which uses internal modules (namespaces) to one which is usable with external modules
* This function is duplicated in the `vscode` repo. * This function is duplicated in the `vscode` repo.
* @param {string} contents
*/ */
function toExternalDTS(contents: string): string { function toExternalDTS(contents) {
let lines = contents.split(/\r\n|\r|\n/); const lines = contents.split(/\r\n|\r|\n/);
let killNextCloseCurlyBrace = false; let killNextCloseCurlyBrace = false;
for (let i = 0; i < lines.length; i++) { for (let i = 0; i < lines.length; i++) {
let line = lines[i]; const line = lines[i];
if (killNextCloseCurlyBrace) { if (killNextCloseCurlyBrace) {
if ('}' === line) { if ('}' === line) {
@ -399,20 +327,8 @@ function toExternalDTS(contents: string): string {
lines[i] = line.replace('declare namespace monaco.', 'export namespace '); lines[i] = line.replace('declare namespace monaco.', 'export namespace ');
} }
if (line.indexOf('declare let MonacoEnvironment') === 0) { if (line.indexOf('declare var MonacoEnvironment') === 0) {
lines[i] = [ lines[i] = `declare global {\n var MonacoEnvironment: Environment | undefined;\n}`;
'declare global {',
' let MonacoEnvironment: Environment | undefined;',
'',
' interface Window {',
' MonacoEnvironment?: Environment | undefined;',
' }',
'}',
''
].join('\n');
}
if (line.indexOf(' MonacoEnvironment?') === 0) {
lines[i] = ` MonacoEnvironment?: Environment | undefined;`;
} }
} }
return lines.join('\n').replace(/\n\n\n+/g, '\n\n'); return lines.join('\n').replace(/\n\n\n+/g, '\n\n');

View file

@ -122,66 +122,6 @@ export function buildESM(options: { base: string; entryPoints: string[]; externa
}); });
} }
function buildOneAMD(
type: 'dev' | 'min',
options: {
base: string;
entryPoint: string;
amdModuleId: string;
amdDependencies?: string[];
external?: string[];
}
) {
if (!options.amdDependencies) {
options.amdDependencies = [];
}
options.amdDependencies.unshift('require');
const opts: esbuild.BuildOptions = {
entryPoints: [options.entryPoint],
bundle: true,
target: 'esnext',
format: 'iife',
drop: ['debugger'],
define: {
AMD: 'true'
},
globalName: 'moduleExports',
banner: {
js: `${bundledFileHeader}define("${options.amdModuleId}", [${(options.amdDependencies || [])
.map((dep) => `"${dep}"`)
.join(',')}],(require)=>{`
},
footer: {
js: 'return moduleExports;\n});'
},
outbase: `src/${options.base}`,
outdir: `out/languages/bundled/amd-${type}/vs/${options.base}/`,
plugins: [
alias({
'vscode-nls': path.join(__dirname, '../build/fillers/vscode-nls.ts'),
'monaco-editor-core': path.join(__dirname, '../src/fillers/monaco-editor-core-amd.ts')
})
],
external: ['vs/editor/editor.api', ...(options.external || [])]
};
if (type === 'min') {
opts.minify = true;
}
build(opts);
}
export function buildAMD(options: {
base: string;
entryPoint: string;
amdModuleId: string;
amdDependencies?: string[];
external?: string[];
}) {
buildOneAMD('dev', options);
buildOneAMD('min', options);
}
function getGitVersion() { function getGitVersion() {
const git = path.join(REPO_ROOT, '.git'); const git = path.join(REPO_ROOT, '.git');
const headPath = path.join(git, 'HEAD'); const headPath = path.join(git, 'HEAD');

View file

@ -1,28 +0,0 @@
## Integrating the AMD version of the Monaco Editor
Here is the most basic HTML page that embeds the editor using AMD.
More self-contained samples are available in the [samples folder](../samples/).
```html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>
<body>
<div id="container" style="width:800px;height:600px;border:1px solid grey"></div>
<script src="monaco-editor/min/vs/loader.js"></script>
<script>
require.config({ paths: { vs: 'monaco-editor/min/vs' } });
require(['vs/editor/editor.main'], function () {
var editor = monaco.editor.create(document.getElementById('container'), {
value: ['function x() {', '\tconsole.log("Hello world!");', '}'].join('\n'),
language: 'javascript'
});
});
</script>
</body>
</html>
```

2449
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
{ {
"name": "monaco-editor", "name": "monaco-editor",
"version": "0.52.0", "version": "0.53.0",
"vscodeRef": "493330cdc6475247184ea459c66776c3da12cd2d", "vscodeRef": "e296bdfe0313d571a6f58399b22afd199f6da454",
"private": true, "private": true,
"description": "A browser based code editor", "description": "A browser based code editor",
"homepage": "https://github.com/microsoft/monaco-editor", "homepage": "https://github.com/microsoft/monaco-editor",
@ -9,8 +9,6 @@
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"import-typescript": "ts-node ./build/importTypescript", "import-typescript": "ts-node ./build/importTypescript",
"playwright-install": "node ./node_modules/playwright/install.js",
"playwright-install-deps": "playwright install-deps",
"postinstall": "ts-node ./build/postinstall", "postinstall": "ts-node ./build/postinstall",
"prettier-check": "prettier --check .", "prettier-check": "prettier --check .",
"prettier": "prettier --write .", "prettier": "prettier --write .",
@ -22,13 +20,14 @@
"package-for-smoketest-vite": "ts-node ./test/smoke/package-vite", "package-for-smoketest-vite": "ts-node ./test/smoke/package-vite",
"smoketest": "node ./test/smoke/runner.js", "smoketest": "node ./test/smoke/runner.js",
"smoketest-debug": "node ./test/smoke/runner.js --debug-tests", "smoketest-debug": "node ./test/smoke/runner.js --debug-tests",
"test": "mocha test/unit/all.js && ts-node ./build/check-samples", "test": "ts-node ./build/check-samples",
"deps-all-remove": "ts-node ./build/npm/removeAll", "deps-all-remove": "ts-node ./build/npm/removeAll",
"deps-all-install": "ts-node ./build/npm/installAll", "deps-all-install": "ts-node ./build/npm/installAll",
"update-actions": "pin-github-action ./.github/workflows/website.yml", "update-actions": "pin-github-action ./.github/workflows/website.yml",
"watch": "tsc -w -p ./src", "watch": "tsc -w -p ./src",
"build": "ts-node ./build/build-languages", "build-languages": "ts-node ./build/build-languages",
"build-monaco-editor": "npm run build && ts-node ./build/build-monaco-editor" "build-monaco-editor": "ts-node ./build/build-monaco-editor",
"build": "npm run build-languages && npm run build-monaco-editor"
}, },
"typings": "./esm/vs/editor/editor.api.d.ts", "typings": "./esm/vs/editor/editor.api.d.ts",
"module": "./esm/vs/editor/editor.main.js", "module": "./esm/vs/editor/editor.main.js",
@ -37,13 +36,15 @@
"url": "https://github.com/microsoft/monaco-editor" "url": "https://github.com/microsoft/monaco-editor"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.53.2",
"@types/mocha": "^9.1.0", "@types/mocha": "^9.1.0",
"@types/shelljs": "^0.8.11", "@types/shelljs": "^0.8.11",
"@types/trusted-types": "^1.0.6",
"@typescript/vfs": "^1.3.5", "@typescript/vfs": "^1.3.5",
"chai": "^4.3.6", "chai": "^4.3.6",
"clean-css": "^5.2.4", "clean-css": "^5.2.4",
"css-loader": "^6.7.1", "css-loader": "^6.7.1",
"esbuild": "^0.20.0", "esbuild": "^0.25.9",
"esbuild-plugin-alias": "^0.2.1", "esbuild-plugin-alias": "^0.2.1",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"glob": "^7.2.0", "glob": "^7.2.0",
@ -52,10 +53,9 @@
"jsdom": "^19.0.0", "jsdom": "^19.0.0",
"jsonc-parser": "^3.0.0", "jsonc-parser": "^3.0.0",
"mocha": "^9.2.0", "mocha": "^9.2.0",
"monaco-editor-core": "0.52.0-rc2", "monaco-editor-core": "^0.54.0-dev-20250926",
"parcel": "^2.7.0", "parcel": "^2.7.0",
"pin-github-action": "^1.8.0", "pin-github-action": "^1.8.0",
"playwright": "^1.32.2",
"prettier": "^2.5.1", "prettier": "^2.5.1",
"pretty-quick": "^3.1.3", "pretty-quick": "^3.1.3",
"requirejs": "^2.3.7", "requirejs": "^2.3.7",
@ -64,7 +64,7 @@
"terser": "^5.14.2", "terser": "^5.14.2",
"ts-node": "^10.6.0", "ts-node": "^10.6.0",
"typescript": "^5.4.5", "typescript": "^5.4.5",
"vite": "^3.2.8", "vite": "^7.1.5",
"vscode-css-languageservice": "6.2.14", "vscode-css-languageservice": "6.2.14",
"vscode-html-languageservice": "5.2.0", "vscode-html-languageservice": "5.2.0",
"vscode-json-languageservice": "5.3.11", "vscode-json-languageservice": "5.3.11",

View file

@ -1,28 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link
rel="stylesheet"
data-name="vs/editor/editor.main"
href="../node_modules/monaco-editor/min/vs/editor/editor.main.css"
/>
</head>
<body>
<h2>Monaco Editor Sync Loading Sample</h2>
<div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div>
<script>
var require = { paths: { vs: '../node_modules/monaco-editor/min/vs' } };
</script>
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script>
<script src="../node_modules/monaco-editor/min/vs/editor/editor.main.js"></script>
<script>
var editor = monaco.editor.create(document.getElementById('container'), {
value: ['function x() {', '\tconsole.log("Hello world!");', '}'].join('\n'),
language: 'javascript'
});
</script>
</body>
</html>

2
samples/legacy/README.md Normal file
View file

@ -0,0 +1,2 @@
These AMD samples are not supported anymore and will be removed in future releases.
Please use the ESM version of the editor!

View file

@ -7,9 +7,9 @@
<h2>Monaco Diff Editor Sample</h2> <h2>Monaco Diff Editor Sample</h2>
<div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div> <div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div>
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script> <script src="../../node_modules/monaco-editor/min/vs/loader.js"></script>
<script> <script>
require.config({ paths: { vs: '../node_modules/monaco-editor/min/vs' } }); require.config({ paths: { vs: '../../node_modules/monaco-editor/min/vs' } });
require(['vs/editor/editor.main'], function () { require(['vs/editor/editor.main'], function () {
var diffEditor = monaco.editor.createDiffEditor(document.getElementById('container')); var diffEditor = monaco.editor.createDiffEditor(document.getElementById('container'));

View file

@ -9,9 +9,9 @@
<div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div> <div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div>
<!-- OR ANY OTHER AMD LOADER HERE INSTEAD OF loader.js --> <!-- OR ANY OTHER AMD LOADER HERE INSTEAD OF loader.js -->
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script> <script src="../../node_modules/monaco-editor/min/vs/loader.js"></script>
<script> <script>
require.config({ paths: { vs: '../node_modules/monaco-editor/min/vs' } }); require.config({ paths: { vs: '../../node_modules/monaco-editor/min/vs' } });
require(['vs/editor/editor.main'], function () { require(['vs/editor/editor.main'], function () {
var editor = monaco.editor.create(document.getElementById('container'), { var editor = monaco.editor.create(document.getElementById('container'), {

View file

@ -15,7 +15,7 @@
</head> </head>
<body> <body>
<div id="container" style="width: 100%; height: 100%"></div> <div id="container" style="width: 100%; height: 100%"></div>
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script> <script src="../../node_modules/monaco-editor/min/vs/loader.js"></script>
<script> <script>
require.config({ paths: { vs: '../node_modules/monaco-editor/min/vs' } }); require.config({ paths: { vs: '../node_modules/monaco-editor/min/vs' } });

View file

@ -7,9 +7,9 @@
<h2>Monaco Editor Localization Sample</h2> <h2>Monaco Editor Localization Sample</h2>
<div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div> <div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div>
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script> <script src="../../node_modules/monaco-editor/min/vs/loader.js"></script>
<script> <script>
require.config({ paths: { vs: '../node_modules/monaco-editor/min/vs' } }); require.config({ paths: { vs: '../../node_modules/monaco-editor/min/vs' } });
require.config({ require.config({
'vs/nls': { 'vs/nls': {

View file

@ -7,9 +7,9 @@
<h2>Monarch Tokenizer Sample</h2> <h2>Monarch Tokenizer Sample</h2>
<div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div> <div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div>
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script> <script src="../../node_modules/monaco-editor/min/vs/loader.js"></script>
<script> <script>
require.config({ paths: { vs: '../node_modules/monaco-editor/min/vs' } }); require.config({ paths: { vs: '../../node_modules/monaco-editor/min/vs' } });
require(['vs/editor/editor.main'], function () { require(['vs/editor/editor.main'], function () {
monaco.languages.register({ monaco.languages.register({

View file

@ -13,7 +13,7 @@
crossorigin="anonymous" crossorigin="anonymous"
></script> ></script>
<script> <script>
require.config({ paths: { vs: '../node_modules/monaco-editor/min/vs' } }); require.config({ paths: { vs: '../../node_modules/monaco-editor/min/vs' } });
require(['vs/editor/editor.main'], function () { require(['vs/editor/editor.main'], function () {
var editor = monaco.editor.create(document.getElementById('container'), { var editor = monaco.editor.create(document.getElementById('container'), {

View file

@ -7,7 +7,7 @@
/* We must define the font face outside the shadowroot */ /* We must define the font face outside the shadowroot */
@font-face { @font-face {
font-family: 'codicon'; font-family: 'codicon';
src: url('../node_modules/monaco-editor/min/vs/base/browser/ui/codicons/codicon/codicon.ttf') src: url('../../node_modules/monaco-editor/min/vs/base/browser/ui/codicons/codicon/codicon.ttf')
format('truetype'); format('truetype');
} }
</style> </style>
@ -17,10 +17,10 @@
<div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div> <div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div>
<!-- OR ANY OTHER AMD LOADER HERE INSTEAD OF loader.js --> <!-- OR ANY OTHER AMD LOADER HERE INSTEAD OF loader.js -->
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script> <script src="../../node_modules/monaco-editor/min/vs/loader.js"></script>
<script> <script>
require.config({ require.config({
paths: { vs: '../node_modules/monaco-editor/min/vs' }, paths: { vs: '../../node_modules/monaco-editor/min/vs' },
'vs/css': { disabled: true } 'vs/css': { disabled: true }
}); });
@ -36,7 +36,7 @@
const innerStyle = document.createElement('style'); const innerStyle = document.createElement('style');
innerStyle.innerText = innerStyle.innerText =
'@import "../node_modules/monaco-editor/min/vs/editor/editor.main.css";'; '@import "../../node_modules/monaco-editor/min/vs/editor/editor.main.css";';
shadowRoot.appendChild(innerStyle); shadowRoot.appendChild(innerStyle);
require(['vs/editor/editor.main'], function () { require(['vs/editor/editor.main'], function () {

View file

@ -8,9 +8,9 @@
<div id="container1" style="width: 400px; height: 200px; border: 1px solid grey"></div> <div id="container1" style="width: 400px; height: 200px; border: 1px solid grey"></div>
<div id="container2" style="width: 400px; height: 200px; border: 1px solid grey"></div> <div id="container2" style="width: 400px; height: 200px; border: 1px solid grey"></div>
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script> <script src="../../node_modules/monaco-editor/min/vs/loader.js"></script>
<script> <script>
require.config({ paths: { vs: '../node_modules/monaco-editor/min/vs' } }); require.config({ paths: { vs: '../../node_modules/monaco-editor/min/vs' } });
require(['vs/editor/editor.main'], function () { require(['vs/editor/editor.main'], function () {
var model = monaco.editor.createModel( var model = monaco.editor.createModel(

View file

@ -9,13 +9,13 @@
<h2>Monaco Editor with Trusted Types Sample</h2> <h2>Monaco Editor with Trusted Types Sample</h2>
<div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div> <div id="container" style="width: 800px; height: 600px; border: 1px solid grey"></div>
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script> <script src="../../node_modules/monaco-editor/min/vs/loader.js"></script>
<script> <script>
// Allow monaco-editor to load scripts from its own paths only // Allow monaco-editor to load scripts from its own paths only
var scriptLoadingPolicy = { var scriptLoadingPolicy = {
createScriptURL: function allowOnlyMonacoPaths(url) { createScriptURL: function allowOnlyMonacoPaths(url) {
if ( if (
url.indexOf('../node_modules/monaco-editor/min/vs/') === 0 && url.indexOf('../../node_modules/monaco-editor/min/vs/') === 0 &&
url.lastIndexOf('..') == 0 url.lastIndexOf('..') == 0
) { ) {
return url; return url;
@ -27,7 +27,7 @@
scriptLoadingPolicy = trustedTypes.createPolicy('monaco-editor', scriptLoadingPolicy); scriptLoadingPolicy = trustedTypes.createPolicy('monaco-editor', scriptLoadingPolicy);
} }
require.config({ require.config({
paths: { vs: '../node_modules/monaco-editor/min/vs' }, paths: { vs: '../../node_modules/monaco-editor/min/vs' },
trustedTypesPolicy: scriptLoadingPolicy trustedTypesPolicy: scriptLoadingPolicy
}); });

3727
samples/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -15,15 +15,15 @@
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"glob": "^7.2.0", "glob": "^7.2.0",
"html-webpack-plugin": "^5.5.0", "html-webpack-plugin": "^5.5.0",
"monaco-editor": "^0.53.0-dev-20250905",
"monaco-editor-webpack-plugin": "^7.0.1", "monaco-editor-webpack-plugin": "^7.0.1",
"monaco-editor": "^0.32.1",
"style-loader": "^3.3.1", "style-loader": "^3.3.1",
"terser-webpack-plugin": "^5.3.1", "terser-webpack-plugin": "^5.3.1",
"ts-loader": "^9.2.6", "ts-loader": "^9.2.6",
"typescript": "^5.4.5", "typescript": "^5.4.5",
"webpack": "^5.101.3",
"webpack-cli": "^4.9.2", "webpack-cli": "^4.9.2",
"webpack-dev-server": "^5.2.1", "webpack-dev-server": "^5.2.1",
"webpack": "^5.76.0",
"yaserver": "^0.4.0" "yaserver": "^0.4.0"
}, },
"overrides": { "overrides": {

View file

@ -1,13 +1,13 @@
import { mkdir, rm } from 'fs/promises'; import { rm } from 'fs/promises';
import { join, resolve } from 'path'; import { join } from 'path';
import { PackageJson, group, gitShallowClone, run, writeJsonFile, getNightlyVersion } from '../lib'; import { PackageJson, group, gitShallowClone, run, writeJsonFile, getNightlyVersion } from '../lib';
import { getNightlyEnv } from './env'; import { getNightlyEnv } from './env';
const selfPath = __dirname; const selfPath = __dirname;
const rootPath = join(selfPath, '..', '..'); const rootPath = join(selfPath, '..', '..');
const dependenciesPath = join(rootPath, 'dependencies'); const dependenciesPath = join(rootPath, 'dependencies');
const vscodePath = resolve(dependenciesPath, 'vscode'); const vscodePath = join(dependenciesPath, 'vscode');
const monacoEditorPackageJsonPath = resolve(rootPath, 'package.json'); const monacoEditorPackageJsonPath = join(rootPath, 'package.json');
async function prepareMonacoEditorCoreReleaseStableOrNightly() { async function prepareMonacoEditorCoreReleaseStableOrNightly() {
const monacoEditorPackageJson = require(monacoEditorPackageJsonPath) as { const monacoEditorPackageJson = require(monacoEditorPackageJsonPath) as {
@ -37,8 +37,6 @@ async function prepareMonacoEditorCoreReleaseStableOrNightly() {
} }
async function prepareMonacoEditorCoreRelease(version: string, vscodeRef: string) { async function prepareMonacoEditorCoreRelease(version: string, vscodeRef: string) {
await mkdir(vscodePath, { recursive: true });
await rm(dependenciesPath, { force: true, recursive: true }); await rm(dependenciesPath, { force: true, recursive: true });
let vscodeCommitId: string; let vscodeCommitId: string;
@ -62,10 +60,7 @@ async function prepareMonacoEditorCoreRelease(version: string, vscodeRef: string
}); });
await group('Set Version', async () => { await group('Set Version', async () => {
const monacoEditorCorePackageJsonSourcePath = resolve( const monacoEditorCorePackageJsonSourcePath = join(vscodePath, './build/monaco/package.json');
vscodePath,
'./build/monaco/package.json'
);
const packageJson = require(monacoEditorCorePackageJsonSourcePath) as PackageJson; const packageJson = require(monacoEditorCorePackageJsonSourcePath) as PackageJson;
packageJson.version = version; packageJson.version = version;
// This ensures we can always figure out which commit monaco-editor-core was built from // This ensures we can always figure out which commit monaco-editor-core was built from
@ -74,8 +69,47 @@ async function prepareMonacoEditorCoreRelease(version: string, vscodeRef: string
}); });
await group('Building & Testing', async () => { await group('Building & Testing', async () => {
await run(resolve(selfPath, './monaco-editor-core.sh'), { cwd: vscodePath }); // Install dependencies
await buildAndTest();
}); });
} }
async function buildAndTest() {
await run('npm install', { cwd: vscodePath });
await run('npm run playwright-install', { cwd: vscodePath });
// Run checks and compilation
await run('npm run gulp hygiene', { cwd: vscodePath });
await run('npm run valid-layers-check', { cwd: vscodePath });
await run('npm run compile', { cwd: join(vscodePath, 'build') });
await run('npm run eslint', { cwd: vscodePath });
await run('npm run monaco-compile-check', { cwd: vscodePath });
await run('npm run --max_old_space_size=4095 compile', { cwd: vscodePath });
// Build editor distribution
await run('npm run gulp editor-distro', { cwd: vscodePath });
return; // To save CI time.
// Run browser tests
await run('npm run test-browser --browser chromium', { cwd: vscodePath });
// TypeScript typings test
await run('mkdir typings-test', { cwd: vscodePath });
const typingsTestDir = join(vscodePath, 'typings-test');
await run('npm init -yp', { cwd: typingsTestDir });
await run('../node_modules/.bin/tsc --init', { cwd: typingsTestDir });
await run('echo "import \'../out-monaco-editor-core\';" > a.ts', { cwd: typingsTestDir });
await run('../node_modules/.bin/tsc --noEmit', { cwd: typingsTestDir });
// Monaco tests
const testMonacoDir = join(vscodePath, 'test/monaco');
await run('npm run esm-check', { cwd: testMonacoDir });
await run('npm run bundle-webpack', { cwd: testMonacoDir });
await run('npm run compile', { cwd: testMonacoDir });
await run('npm test', { cwd: testMonacoDir });
}
//buildAndTest();
//prepareMonacoEditorCoreRelease('0.99.0', 'main');
prepareMonacoEditorCoreReleaseStableOrNightly(); prepareMonacoEditorCoreReleaseStableOrNightly();

View file

@ -46,8 +46,26 @@ async function prepareMonacoEditorRelease(monacoEditorCoreVersion: string) {
const packageJson = JSON.parse( const packageJson = JSON.parse(
await readFile(monacoEditorPackageJsonPath, { encoding: 'utf-8' }) await readFile(monacoEditorPackageJsonPath, { encoding: 'utf-8' })
) as PackageJson; ) as PackageJson;
packageJson.version = monacoEditorCoreVersion; packageJson.version = monacoEditorCoreVersion;
packageJson.devDependencies['monaco-editor-core'] = monacoEditorCoreVersion; packageJson.devDependencies['monaco-editor-core'] = monacoEditorCoreVersion;
const monacoEditorCorePackageJson = JSON.parse(
await readFile(monacoEditorCorePackageJsonPath, { encoding: 'utf-8' })
) as PackageJson;
if (monacoEditorCorePackageJson.dependencies) {
if (!packageJson.dependencies) {
packageJson.dependencies = {};
}
objectMergeThrowIfSet(
packageJson.dependencies,
monacoEditorCorePackageJson.dependencies,
'dependencies'
);
}
await writeJsonFile(monacoEditorPackageJsonPath, packageJson); await writeJsonFile(monacoEditorPackageJsonPath, packageJson);
}); });
@ -68,8 +86,32 @@ async function prepareMonacoEditorRelease(monacoEditorCoreVersion: string) {
}); });
await group('Building & Testing', async () => { await group('Building & Testing', async () => {
await run(resolve(selfPath, './monaco-editor.sh'), { cwd: rootPath }); // TODO@hediet: await run('npm run prettier-check', { cwd: rootPath });
await run('npm run build', { cwd: rootPath });
await run('npm test', { cwd: rootPath });
await run('npm run compile', { cwd: resolve(rootPath, 'webpack-plugin') });
await run('npm run package-for-smoketest-webpack', { cwd: rootPath });
await run('npm run package-for-smoketest-esbuild', { cwd: rootPath });
await run('npm run package-for-smoketest-vite', { cwd: rootPath });
await run('npm run smoketest', { cwd: rootPath });
// npm package is now ready to be published in ./out/monaco-editor
}); });
} }
function objectMergeThrowIfSet(
target: Record<string, any>,
source: Record<string, any>,
fieldName: string
): void {
for (const [key, value] of Object.entries(source)) {
if (key in target) {
throw new Error(
`Cannot merge ${fieldName}: property '${key}' already exists in target with value '${target[key]}', would be overridden with '${value}'`
);
}
target[key] = value;
}
}
prepareMonacoEditorReleaseStableOrNightly(); prepareMonacoEditorReleaseStableOrNightly();

View file

@ -1,34 +0,0 @@
#!/bin/bash
set -e
# cwd must be the vscode repository.
yarn --frozen-lockfile --network-timeout 180000
yarn playwright-install
yarn gulp hygiene
yarn valid-layers-check
yarn --cwd build compile
yarn eslint
yarn monaco-compile-check
yarn --max_old_space_size=4095 compile
yarn test-browser --browser chromium
yarn gulp editor-distro
mkdir typings-test
cd typings-test
yarn init -yp
../node_modules/.bin/tsc --init
echo "import '../out-monaco-editor-core';" > a.ts
../node_modules/.bin/tsc --noEmit
cd ..
cd test/monaco
yarn run esm-check
yarn run bundle-webpack
yarn run compile
yarn test
cd ../..
# npm package is now in dependencies/vscode/out-monaco-editor-core, ready to be published

View file

@ -1,29 +0,0 @@
#!/bin/bash
set -e
# Install OS Dependencies for Playwright
sudo npm run playwright-install-deps
# Check prettier
npm run prettier-check
# Build
npm run build-monaco-editor
# Run unit tests
npm test
# Compile webpack plugin
npm run compile --prefix webpack-plugin
# Package using webpack plugin
npm run package-for-smoketest-webpack
# Package using esbuild
npm run package-for-smoketest-esbuild
# Package using vite
npm run package-for-smoketest-vite
# Package using parcel
# npm run package-for-smoketest-parcel --prefix test/smoke/parcel
# Disabled for now, as the parcel bundler cannot deal with VS Code process variable
# Run smoke test
npm run smoketest
# npm package is now ready to be published in ./out/monaco-editor

View file

@ -92,4 +92,5 @@ export interface PackageJson {
vscodeCommitId?: string; vscodeCommitId?: string;
monacoCommitId?: string; monacoCommitId?: string;
devDependencies: Record<string, string>; devDependencies: Record<string, string>;
dependencies?: Record<string, string>;
} }

16
src/common/initialize.ts Normal file
View file

@ -0,0 +1,16 @@
import * as worker from 'monaco-editor-core/esm/vs/editor/editor.worker.start';
let initialized = false;
export function isWorkerInitialized(): boolean {
return initialized;
}
export function initialize(callback: (ctx: any, createData: any) => any): void {
initialized = true;
self.onmessage = (m) => {
worker.start((ctx) => {
return callback(ctx, m.data);
});
};
}

131
src/common/workers.ts Normal file
View file

@ -0,0 +1,131 @@
import { editor } from '../fillers/monaco-editor-core';
function createTrustedTypesPolicy<Options extends TrustedTypePolicyOptions>(
policyName: string,
policyOptions?: Options
):
| undefined
| Pick<
TrustedTypePolicy<Options>,
'name' | Extract<keyof Options, keyof TrustedTypePolicyOptions>
> {
interface IMonacoEnvironment {
createTrustedTypesPolicy<Options extends TrustedTypePolicyOptions>(
policyName: string,
policyOptions?: Options
):
| undefined
| Pick<
TrustedTypePolicy<Options>,
'name' | Extract<keyof Options, keyof TrustedTypePolicyOptions>
>;
}
const monacoEnvironment: IMonacoEnvironment | undefined = (globalThis as any).MonacoEnvironment;
if (monacoEnvironment?.createTrustedTypesPolicy) {
try {
return monacoEnvironment.createTrustedTypesPolicy(policyName, policyOptions);
} catch (err) {
console.error(err);
return undefined;
}
}
try {
return (globalThis as any).trustedTypes?.createPolicy(policyName, policyOptions);
} catch (err) {
console.error(err);
return undefined;
}
}
let ttPolicy: ReturnType<typeof createTrustedTypesPolicy>;
if (
typeof self === 'object' &&
self.constructor &&
self.constructor.name === 'DedicatedWorkerGlobalScope' &&
(globalThis as any).workerttPolicy !== undefined
) {
ttPolicy = (globalThis as any).workerttPolicy;
} else {
ttPolicy = createTrustedTypesPolicy('defaultWorkerFactory', {
createScriptURL: (value) => value
});
}
function getWorker(descriptor: { label: string; moduleId: string }): Worker | Promise<Worker> {
const label = descriptor.label;
// Option for hosts to overwrite the worker script (used in the standalone editor)
interface IMonacoEnvironment {
getWorker?(moduleId: string, label: string): Worker | Promise<Worker>;
getWorkerUrl?(moduleId: string, label: string): string;
}
const monacoEnvironment: IMonacoEnvironment | undefined = (globalThis as any).MonacoEnvironment;
if (monacoEnvironment) {
if (typeof monacoEnvironment.getWorker === 'function') {
return monacoEnvironment.getWorker('workerMain.js', label);
}
if (typeof monacoEnvironment.getWorkerUrl === 'function') {
const workerUrl = monacoEnvironment.getWorkerUrl('workerMain.js', label);
return new Worker(
ttPolicy ? (ttPolicy.createScriptURL(workerUrl) as unknown as string) : workerUrl,
{ name: label, type: 'module' }
);
}
}
// const esmWorkerLocation = descriptor.esmModuleLocation;
// if (esmWorkerLocation) {
// const workerUrl = getWorkerBootstrapUrl(label, esmWorkerLocation.toString(true));
// const worker = new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: label, type: 'module' });
// return whenESMWorkerReady(worker);
// }
throw new Error(
`You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker`
);
}
export function createWebWorker<T extends object>(
opts: IWebWorkerOptions
): editor.MonacoWebWorker<T> {
const worker = Promise.resolve(
getWorker({
label: opts.label ?? 'monaco-editor-worker',
moduleId: opts.moduleId
})
).then((w) => {
w.postMessage('ignore');
w.postMessage(opts.createData);
return w;
});
return editor.createWebWorker<T>({
worker,
host: opts.host,
keepIdleModels: opts.keepIdleModels
});
}
export interface IWebWorkerOptions {
/**
* The AMD moduleId to load.
* It should export a function `create` that should return the exported proxy.
*/
moduleId: string;
/**
* The data to send over when calling create on the module.
*/
createData?: any;
/**
* A label to be used to identify the web worker for debugging purposes.
*/
label?: string;
/**
* An object that can be used by the web worker to make calls back to the main thread.
*/
host?: any;
/**
* Keep idle models.
* Defaults to false, which means that idle models will stop syncing after a while.
*/
keepIdleModels?: boolean;
}

16
src/editor/editor.main.ts Normal file
View file

@ -0,0 +1,16 @@
import { createWebWorker } from '../common/workers.js';
import '../basic-languages/monaco.contribution.js';
import '../language/css/monaco.contribution.js';
import '../language/html/monaco.contribution.js';
import '../language/json/monaco.contribution.js';
import '../language/typescript/monaco.contribution.js';
import * as monaco from 'monaco-editor-core';
export * from 'monaco-editor-core';
const existingCreateWebWorker = monaco.editor.createWebWorker;
monaco.editor.createWebWorker = function (options: any) {
if (options.worker === undefined) {
return createWebWorker(options);
}
return existingCreateWebWorker(options);
} as any;

View file

@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { initialize, isWorkerInitialized } from '../common/initialize';
import * as worker from 'monaco-editor-core/esm/vs/editor/editor.worker.start';
// This is to preserve previous behavior.
self.onmessage = () => {
if (!isWorkerInitialized()) {
worker.start(() => {
return {};
});
} else {
// this is handled because the worker is already initialized
}
};
export { initialize };

View file

@ -1,11 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// Resolves with the global monaco API
/// <reference path="./editor.api.d.ts" />
import * as api from 'vs/editor/editor.api';
export = api;

View file

@ -3,12 +3,12 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as worker from 'monaco-editor-core/esm/vs/editor/editor.worker'; import { initialize } from '../../common/initialize';
import { CSSWorker } from './cssWorker'; import { CSSWorker } from './cssWorker';
self.onmessage = () => { self.onmessage = () => {
// ignore the first message // ignore the first message
worker.initialize((ctx, createData) => { initialize((ctx, createData) => {
return new CSSWorker(ctx, createData); return new CSSWorker(ctx, createData);
}); });
}; };

View file

@ -6,6 +6,7 @@
import { LanguageServiceDefaults } from './monaco.contribution'; import { LanguageServiceDefaults } from './monaco.contribution';
import type { CSSWorker } from './cssWorker'; import type { CSSWorker } from './cssWorker';
import { editor, IDisposable, Uri } from '../../fillers/monaco-editor-core'; import { editor, IDisposable, Uri } from '../../fillers/monaco-editor-core';
import { createWebWorker } from '../../common/workers';
const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000; // 2min const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000; // 2min
@ -55,7 +56,7 @@ export class WorkerManager {
this._lastUsedTime = Date.now(); this._lastUsedTime = Date.now();
if (!this._client) { if (!this._client) {
this._worker = editor.createWebWorker<CSSWorker>({ this._worker = createWebWorker<CSSWorker>({
// module that exports the create() method and returns a `CSSWorker` instance // module that exports the create() method and returns a `CSSWorker` instance
moduleId: 'vs/language/css/cssWorker', moduleId: 'vs/language/css/cssWorker',

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as worker from 'monaco-editor-core/esm/vs/editor/editor.worker'; import * as worker from '../../common/initialize';
import { HTMLWorker } from './htmlWorker'; import { HTMLWorker } from './htmlWorker';
self.onmessage = () => { self.onmessage = () => {

View file

@ -6,6 +6,7 @@
import { LanguageServiceDefaults } from './monaco.contribution'; import { LanguageServiceDefaults } from './monaco.contribution';
import type { HTMLWorker } from './htmlWorker'; import type { HTMLWorker } from './htmlWorker';
import { Uri, IDisposable, editor } from '../../fillers/monaco-editor-core'; import { Uri, IDisposable, editor } from '../../fillers/monaco-editor-core';
import { createWebWorker } from '../../common/workers';
const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000; // 2min const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000; // 2min
@ -55,7 +56,7 @@ export class WorkerManager {
this._lastUsedTime = Date.now(); this._lastUsedTime = Date.now();
if (!this._client) { if (!this._client) {
this._worker = editor.createWebWorker<HTMLWorker>({ this._worker = createWebWorker<HTMLWorker>({
// module that exports the create() method and returns a `HTMLWorker` instance // module that exports the create() method and returns a `HTMLWorker` instance
moduleId: 'vs/language/html/htmlWorker', moduleId: 'vs/language/html/htmlWorker',

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as worker from 'monaco-editor-core/esm/vs/editor/editor.worker'; import * as worker from '../../common/initialize';
import { JSONWorker } from './jsonWorker'; import { JSONWorker } from './jsonWorker';
self.onmessage = () => { self.onmessage = () => {

View file

@ -6,6 +6,7 @@
import { LanguageServiceDefaults } from './monaco.contribution'; import { LanguageServiceDefaults } from './monaco.contribution';
import type { JSONWorker } from './jsonWorker'; import type { JSONWorker } from './jsonWorker';
import { IDisposable, Uri, editor } from '../../fillers/monaco-editor-core'; import { IDisposable, Uri, editor } from '../../fillers/monaco-editor-core';
import { createWebWorker } from '../../common/workers';
const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000; // 2min const STOP_WHEN_IDLE_FOR = 2 * 60 * 1000; // 2min
@ -55,7 +56,7 @@ export class WorkerManager {
this._lastUsedTime = Date.now(); this._lastUsedTime = Date.now();
if (!this._client) { if (!this._client) {
this._worker = editor.createWebWorker<JSONWorker>({ this._worker = createWebWorker<JSONWorker>({
// module that exports the create() method and returns a `JSONWorker` instance // module that exports the create() method and returns a `JSONWorker` instance
moduleId: 'vs/language/json/jsonWorker', moduleId: 'vs/language/json/jsonWorker',

View file

@ -3,6 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
declare module 'monaco-editor-core/esm/vs/editor/editor.worker' { declare module 'monaco-editor-core/esm/vs/editor/editor.worker.start' {
export function initialize(callback: (ctx: any, createData: any) => any): void; import type { worker } from 'monaco-editor-core';
export function start<THost extends object, TClient extends object>(createClient: (ctx: worker.IWorkerContext<THost>) => TClient): TClient;
} }

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { initialize } from 'monaco-editor-core/esm/vs/editor/editor.worker'; import { initialize } from '../../common/initialize';
import * as ts from './lib/typescriptServices'; import * as ts from './lib/typescriptServices';
import { ICreateData, TypeScriptWorker, create } from './tsWorker'; import { ICreateData, TypeScriptWorker, create } from './tsWorker';
import { worker } from '../../fillers/monaco-editor-core'; import { worker } from '../../fillers/monaco-editor-core';

View file

@ -6,6 +6,7 @@
import { LanguageServiceDefaults } from './monaco.contribution'; import { LanguageServiceDefaults } from './monaco.contribution';
import type { TypeScriptWorker } from './tsWorker'; import type { TypeScriptWorker } from './tsWorker';
import { editor, Uri, IDisposable } from '../../fillers/monaco-editor-core'; import { editor, Uri, IDisposable } from '../../fillers/monaco-editor-core';
import { createWebWorker } from '../../common/workers';
export class WorkerManager { export class WorkerManager {
private _configChangeListener: IDisposable; private _configChangeListener: IDisposable;
@ -58,7 +59,7 @@ export class WorkerManager {
private _getClient(): Promise<TypeScriptWorker> { private _getClient(): Promise<TypeScriptWorker> {
if (!this._client) { if (!this._client) {
this._client = (async () => { this._client = (async () => {
this._worker = editor.createWebWorker<TypeScriptWorker>({ this._worker = createWebWorker<TypeScriptWorker>({
// module that exports the create() method and returns a `TypeScriptWorker` instance // module that exports the create() method and returns a `TypeScriptWorker` instance
moduleId: 'vs/language/typescript/tsWorker', moduleId: 'vs/language/typescript/tsWorker',

View file

@ -1,39 +0,0 @@
/* This fix ensures that old nls-plugin configurations are still respected by the new localization solution. */
/* We should try to avoid this file and find a different solution. */
/* Warning: This file still has to work when replacing "\n" with " "! */
/**
* @type {typeof define}
*/
const globalDefine = globalThis.define;
globalDefine('vs/nls.messages-loader', [], function (...args) {
return {
load: (name, req, load, config) => {
const requestedLanguage = config['vs/nls']?.availableLanguages?.['*'];
if (!requestedLanguage || requestedLanguage === 'en') {
load({});
} else {
req([`vs/nls.messages.${requestedLanguage}`], () => {
load({});
});
}
}
};
});
globalDefine(
'vs/nls.messages',
['require', 'exports', 'vs/nls.messages-loader!'],
function (require, exports) {
Object.assign(exports, {
getNLSMessages: () => globalThis._VSCODE_NLS_MESSAGES,
getNLSLanguage: () => globalThis._VSCODE_NLS_LANGUAGE
});
}
);
define = function (...args) {
if (args.length > 0 && args[0] === 'vs/nls.messages') {
return;
}
return globalDefine(...args);
};
define.amd = true;

View file

@ -2,9 +2,13 @@
"compilerOptions": { "compilerOptions": {
"declaration": true, "declaration": true,
"lib": ["dom", "es5", "es2015.collection", "es2015.promise", "es2015.iterable"], "lib": ["dom", "es5", "es2015.collection", "es2015.promise", "es2015.iterable"],
"module": "amd", "module": "esnext",
"moduleResolution": "node", "moduleResolution": "node",
"outDir": "../out/languages/amd-tsc", "outDir": "../out/languages/tsc",
"paths": {
"@/*": ["./*"]
},
"emitDeclarationOnly": true,
"strict": true, "strict": true,
"target": "es5", "target": "es5",
"sourceMap": true, "sourceMap": true,

View file

@ -1,7 +1,5 @@
/// <reference path="../../out/monaco-editor/monaco.d.ts" /> /// <reference path="../../out/monaco-editor/monaco.d.ts" />
define(['require', './samples'], function (require, SAMPLES) { define(['require', './samples'], function (require, SAMPLES) {
const domutils = require('vs/base/browser/dom');
let model = monaco.editor.createModel('', 'plaintext'); let model = monaco.editor.createModel('', 'plaintext');
monaco.languages.typescript.typescriptDefaults.setInlayHintsOptions({ monaco.languages.typescript.typescriptDefaults.setInlayHintsOptions({
@ -167,7 +165,7 @@ define(['require', './samples'], function (require, SAMPLES) {
editor.setScrollTop(r); editor.setScrollTop(r);
if (speed >= 0) { if (speed >= 0) {
domutils.scheduleAtNextAnimationFrame(scroll); requestAnimationFrame(scroll);
} else { } else {
isRunning = false; isRunning = false;
} }
@ -179,7 +177,7 @@ define(['require', './samples'], function (require, SAMPLES) {
isRunning = true; isRunning = true;
r = editor.getScrollTop(); r = editor.getScrollTop();
lastTime = new Date().getTime(); lastTime = new Date().getTime();
domutils.runAtThisOrScheduleAtNextAnimationFrame(scroll); requestAnimationFrame(scroll);
} }
}; };
})() })()

View file

@ -2,7 +2,7 @@
// which can do work on a bg thread. // which can do work on a bg thread.
// This version of the vfs edits the global scope (in the case of a webworker, this is 'self') // This version of the vfs edits the global scope (in the case of a webworker, this is 'self')
importScripts('https://unpkg.com/@typescript/vfs@1.3.0/dist/vfs.globals.js'); import 'https://unpkg.com/@typescript/vfs@1.3.0/dist/vfs.globals.js';
/** @type { import("@typescript/vfs") } */ /** @type { import("@typescript/vfs") } */
const tsvfs = globalThis.tsvfs; const tsvfs = globalThis.tsvfs;

View file

@ -42,7 +42,7 @@ async function runTests() {
// uncomment to shortcircuit and run a specific combo // uncomment to shortcircuit and run a specific combo
// await runTest('webpack', 'chromium'); return; // await runTest('webpack', 'chromium'); return;
/** @type {PackagerKind[]} */ /** @type {PackagerKind[]} */
const testTypes = ['amd', 'webpack', 'esbuild', 'vite']; const testTypes = ['webpack', 'esbuild', 'vite', 'amd'];
// TODO: add parcel! (this currently fails because parcel replaces process with {}) // TODO: add parcel! (this currently fails because parcel replaces process with {})
for (const type of testTypes) { for (const type of testTypes) {

View file

@ -1,70 +0,0 @@
const requirejs = require('requirejs');
const jsdom = require('jsdom');
const glob = require('glob');
const path = require('path');
requirejs.config({
baseUrl: '',
paths: {
'vs/fillers/monaco-editor-core': 'out/languages/amd-tsc/fillers/monaco-editor-core-amd',
'vs/basic-languages': 'out/languages/amd-tsc/basic-languages',
vs: './node_modules/monaco-editor-core/dev/vs'
},
nodeRequire: require
});
const tmp = new jsdom.JSDOM('<!DOCTYPE html><html><body></body></html>');
global.AMD = true;
global.document = tmp.window.document;
global.navigator = tmp.window.navigator;
global.self = global;
global.document.queryCommandSupported = function () {
return false;
};
global.UIEvent = tmp.window.UIEvent;
global.window = {
location: {},
navigator: tmp.window.navigator,
document: {
body: tmp.window.document.body,
addEventListener: (...args) => tmp.window.document.addEventListener(...args)
},
matchMedia: function () {
return {
matches: false,
addEventListener: function () {}
};
},
setInterval: function () {},
setTimeout: function () {}
};
requirejs(
['test/unit/setup'],
function () {
glob(
'out/languages/amd-tsc/basic-languages/*/*.test.js',
{ cwd: path.join(__dirname, '../../') },
function (err, files) {
if (err) {
console.log(err);
return;
}
requirejs(
files.map((f) => f.replace(/^out\/languages\/amd-tsc/, 'vs').replace(/\.js$/, '')),
function () {
run(); // We can launch the tests!
},
function (err) {
console.log(err);
}
);
}
);
},
function (err) {
console.log(err);
process.exit(1);
}
);

View file

@ -1,34 +0,0 @@
define('vs/css', [], {
load: function (name, req, load) {
load({});
}
});
define('vs/nls', [], {
create: function () {
return {
localize: function () {
return 'NO_LOCALIZATION_FOR_YOU';
},
localize2: function () {
return 'NO_LOCALIZATION_FOR_YOU';
},
getConfiguredDefaultLocale: function () {
return undefined;
}
};
},
localize: function () {
return 'NO_LOCALIZATION_FOR_YOU';
},
localize2: function (key, message) {
return { value: 'NO_LOCALIZATION_FOR_YOU', original: message };
},
load: function (name, req, load) {
load({});
}
});
define(['vs/editor/editor.main'], function (api) {
global.monaco = api;
});

View file

@ -14,6 +14,7 @@
"@types/base64-js": "^1.3.0", "@types/base64-js": "^1.3.0",
"@types/bootstrap": "^5.2.0", "@types/bootstrap": "^5.2.0",
"@types/node": "^18.6.1", "@types/node": "^18.6.1",
"@vscode/web-editors": "./vscode-web-editors.tgz",
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"bootstrap": "^5.2.0", "bootstrap": "^5.2.0",
"bootstrap-icons": "^1.9.1", "bootstrap-icons": "^1.9.1",
@ -24,12 +25,11 @@
"mini-css-extract-plugin": "^2.6.1", "mini-css-extract-plugin": "^2.6.1",
"mobx": "^5.15.4", "mobx": "^5.15.4",
"mobx-react": "^6.2.2", "mobx-react": "^6.2.2",
"monaco-editor": "^0.42.0-dev-20230906", "monaco-editor": "^0.53.0",
"react": "^17.0.2", "react": "^17.0.2",
"react-bootstrap": "^2.4.0", "react-bootstrap": "^2.4.0",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"typedoc": "^0.25.12", "typedoc": "^0.25.12"
"@vscode/web-editors": "./vscode-web-editors.tgz"
}, },
"devDependencies": { "devDependencies": {
"@types/classnames": "^2.3.1", "@types/classnames": "^2.3.1",

View file

@ -19,6 +19,7 @@ export interface IMonacoSetup {
loaderConfigPaths: Record<string, string>; loaderConfigPaths: Record<string, string>;
codiconUrl: string; codiconUrl: string;
monacoTypesUrl: string | undefined; monacoTypesUrl: string | undefined;
language?: string;
} }
let loading = false; let loading = false;
@ -57,7 +58,18 @@ async function _loadMonaco(setup: IMonacoSetup): Promise<typeof monaco> {
/** @type {any} */ /** @type {any} */
const req = global.require as any; const req = global.require as any;
req.config({ paths: setup.loaderConfigPaths });
// Configure language if specified
const config: any = { paths: setup.loaderConfigPaths };
if (setup.language) {
config["vs/nls"] = {
availableLanguages: {
"*": setup.language,
},
};
}
req.config(config);
return new Promise((res) => { return new Promise((res) => {
// First load editor.main. If it inlines the plugins, we don't want to try to load them from the server. // First load editor.main. If it inlines the plugins, we don't want to try to load them from the server.
@ -97,7 +109,10 @@ export const prodMonacoSetup = getMonacoSetup(
"node_modules/monaco-editor/min/vs" "node_modules/monaco-editor/min/vs"
); );
export function getMonacoSetup(corePath: string): IMonacoSetup { export function getMonacoSetup(
corePath: string,
language?: string
): IMonacoSetup {
const loaderConfigPaths = { const loaderConfigPaths = {
vs: `${corePath}`, vs: `${corePath}`,
}; };
@ -107,5 +122,6 @@ export function getMonacoSetup(corePath: string): IMonacoSetup {
loaderConfigPaths, loaderConfigPaths,
codiconUrl: `${corePath}/base/browser/ui/codicons/codicon/codicon.ttf`, codiconUrl: `${corePath}/base/browser/ui/codicons/codicon/codicon.ttf`,
monacoTypesUrl: undefined, monacoTypesUrl: undefined,
language,
}; };
} }

View file

@ -89,17 +89,8 @@ export class Home extends React.Component {
<hr /> <hr />
<p className="text-center"> <p className="text-center">
<a href="https://microsoft.com" title="Microsoft"> <a href="https://microsoft.com" title="Microsoft">
<img
src="https://opensource.microsoft.com/assets/images/Microsoft_logo.svg"
alt="Microsoft"
style={{
maxHeight: "23px",
marginBottom: "12px",
}}
/>
</a>
<br />
<small>&copy; {process.env.YEAR} Microsoft</small> <small>&copy; {process.env.YEAR} Microsoft</small>
</a>
</p> </p>
</footer> </footer>
</Page> </Page>

View file

@ -1,7 +1,7 @@
import * as React from "react"; import * as React from "react";
import { PlaygroundModel } from "./PlaygroundModel"; import { PlaygroundModel } from "./PlaygroundModel";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { autorun, observable, reaction } from "mobx"; import { observable, reaction } from "mobx";
import { import {
IMessageFromRunner, IMessageFromRunner,
IMessageToRunner, IMessageToRunner,

View file

@ -390,6 +390,72 @@ export class SettingsDialog extends React.Component<{
</Vertical> </Vertical>
</div> </div>
</ListGroup.Item> </ListGroup.Item>
<ListGroup.Item>
<div className="d-flex gap-2">
<label className="d-flex gap-2">
<span>
Language/Localization
<small className="d-block text-muted">
Configure the Monaco Editor language
for UI elements. Leave unconfigured
to use default English.
</small>
</span>
</label>
<Select
value={ref(
modelSettings.settings,
"language"
)}
values={[
undefined,
"de",
"es",
"fr",
"it",
"ja",
"ko",
"ru",
"zh-cn",
"zh-tw",
]}
getLabel={(v) => {
switch (v) {
case undefined:
return "Unconfigured (English)";
case "de":
return "German (Deutsch)";
case "es":
return "Spanish (Español)";
case "fr":
return "French (Français)";
case "it":
return "Italian (Italiano)";
case "ja":
return "Japanese (日本語)";
case "ko":
return "Korean (한국어)";
case "ru":
return "Russian (Русский)";
case "zh-cn":
return "Chinese Simplified (简体中文)";
case "zh-tw":
return "Chinese Traditional (繁體中文)";
default:
return (
v ||
"Unconfigured (English)"
);
}
}}
style={{
width: 250,
marginLeft: "auto",
}}
/>
</div>
</ListGroup.Item>
</ListGroup> </ListGroup>
</Modal.Body> </Modal.Body>
<Modal.Footer> <Modal.Footer>

View file

@ -88,6 +88,8 @@ export interface Settings {
previewFullScreen: boolean; previewFullScreen: boolean;
autoReload: boolean | undefined; autoReload: boolean | undefined;
language?: string;
} }
export type JsonString<T> = string; export type JsonString<T> = string;
@ -97,14 +99,18 @@ export function toLoaderConfig(settings: Settings): IMonacoSetup {
case "latest": case "latest":
return { return {
...getMonacoSetup( ...getMonacoSetup(
`node_modules/monaco-editor/${settings.latestStability}/vs` `node_modules/monaco-editor/${settings.latestStability}/vs`,
settings.language
), ),
monacoTypesUrl: "node_modules/monaco-editor/monaco.d.ts", monacoTypesUrl: "node_modules/monaco-editor/monaco.d.ts",
}; };
case "npm": case "npm":
const url = `https://cdn.jsdelivr.net/npm/monaco-editor@${settings.npmVersion}`; const url = `https://cdn.jsdelivr.net/npm/monaco-editor@${settings.npmVersion}`;
return { return {
...getMonacoSetup(`${url}/${settings.npmStability}/vs`), ...getMonacoSetup(
`${url}/${settings.npmStability}/vs`,
settings.language
),
monacoTypesUrl: `${url}/monaco.d.ts`, monacoTypesUrl: `${url}/monaco.d.ts`,
}; };
case "custom": case "custom":
@ -143,7 +149,7 @@ export function toLoaderConfig(settings: Settings): IMonacoSetup {
break; break;
} }
const setup = { ...getMonacoSetup(coreUrl) }; const setup = { ...getMonacoSetup(coreUrl, settings.language) };
if ( if (
!setup.monacoTypesUrl && !setup.monacoTypesUrl &&
setup.loaderConfigPaths["vs"] && setup.loaderConfigPaths["vs"] &&
@ -186,6 +192,7 @@ export function getDefaultSettings(): Settings {
}), }),
previewFullScreen: false, previewFullScreen: false,
autoReload: true, autoReload: true,
language: undefined,
}; };
return defaultSettings; return defaultSettings;
} }

View file

@ -7,8 +7,8 @@ import * as webpack from "webpack";
import * as path from "path"; import * as path from "path";
import * as HtmlWebpackPlugin from "html-webpack-plugin"; import * as HtmlWebpackPlugin from "html-webpack-plugin";
import { CleanWebpackPlugin } from "clean-webpack-plugin"; import { CleanWebpackPlugin } from "clean-webpack-plugin";
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
import * as CopyPlugin from "copy-webpack-plugin"; import * as CopyPlugin from "copy-webpack-plugin";
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const r = (file: string) => path.resolve(__dirname, file); const r = (file: string) => path.resolve(__dirname, file);
@ -131,9 +131,6 @@ module.exports = {
}, },
], ],
}), }),
new CopyPlugin({
patterns: [{ from: "../out/languages/", to: "./out/languages/" }],
}),
], ],
} as webpack.Configuration; } as webpack.Configuration;

View file

@ -447,6 +447,11 @@
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.8.tgz#b94a4391c85666c7b73299fd3ad79d4faa435310" resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.8.tgz#b94a4391c85666c7b73299fd3ad79d4faa435310"
integrity sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ== integrity sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==
"@types/trusted-types@^1.0.6":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-1.0.6.tgz#569b8a08121d3203398290d602d84d73c8dcf5da"
integrity sha512-230RC8sFeHoT6sSUlRO6a8cAnclO06eeiq1QDfiv2FGCLWFvvERWgwIQD4FWqD9A69BN7Lzee4OXwoMVnnsWDw==
"@types/uglify-js@*": "@types/uglify-js@*":
version "3.16.0" version "3.16.0"
resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.16.0.tgz#2cf74a0e6ebb6cd54c0d48e509d5bd91160a9602" resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.16.0.tgz#2cf74a0e6ebb6cd54c0d48e509d5bd91160a9602"
@ -2271,10 +2276,12 @@ mobx@^5.15.4:
resolved "https://registry.yarnpkg.com/mobx/-/mobx-5.15.7.tgz#b9a5f2b6251f5d96980d13c78e9b5d8d4ce22665" resolved "https://registry.yarnpkg.com/mobx/-/mobx-5.15.7.tgz#b9a5f2b6251f5d96980d13c78e9b5d8d4ce22665"
integrity sha512-wyM3FghTkhmC+hQjyPGGFdpehrcX1KOXsDuERhfK2YbJemkUhEB+6wzEN639T21onxlfYBmriA1PFnvxTUhcKw== integrity sha512-wyM3FghTkhmC+hQjyPGGFdpehrcX1KOXsDuERhfK2YbJemkUhEB+6wzEN639T21onxlfYBmriA1PFnvxTUhcKw==
monaco-editor@^0.42.0-dev-20230906: monaco-editor@^0.53.0:
version "0.42.0-dev-20230906" version "0.53.0"
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.42.0-dev-20230906.tgz#612a41fcbed662d3873a94ad5f558e6893da2c7d" resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.53.0.tgz#2f485492e0ee822be13b1b45e3092922963737ae"
integrity sha512-UICbxxHu0jYovjOKcwSJkmnJbokiSefro1wDqVJ4OpyzXmS0dYZol+lYPJLIdfb0oUtUTf8840VMAPo5jC+B1Q== integrity sha512-0WNThgC6CMWNXXBxTbaYYcunj08iB5rnx4/G56UOPeL9UVIUGGHA1GR0EWIh9Ebabj7NpCRawQ5b0hfN1jQmYQ==
dependencies:
"@types/trusted-types" "^1.0.6"
mrmime@^1.0.0: mrmime@^1.0.0:
version "1.0.1" version "1.0.1"