repairs amd build

This commit is contained in:
Henning Dieterichs 2025-08-28 12:23:35 +02:00
parent e55f585183
commit 5074e2eca3
20 changed files with 1558 additions and 357 deletions

View file

@ -44,19 +44,21 @@ jobs:
if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }}
run: npm ci --prefix webpack-plugin
- 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}'
# If you want to 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: Link monaco-editor-core
run: npm link
working-directory: ./dependencies/vscode/out-monaco-editor-core
# - name: Link monaco-editor-core
# run: npm link
# working-directory: ./dependencies/vscode/out-monaco-editor-core
- name: Link monaco-editor-core
run: npm link monaco-editor-core
# - name: Link monaco-editor-core
# run: npm link monaco-editor-core
# TODO: prettier formatting
# - name: Check prettier
# run: npm run prettier-check

View file

@ -1,5 +1,9 @@
# Monaco Editor Changelog
## [0.60.0]
- Deprecated `AMD` build.
## [0.52.0]
- 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:
- 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).
It is recommended to develop against the `dev` version, and in production to use the `min` version.
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
@ -60,7 +57,6 @@ Many Monaco related objects often implement the `.dispose()` method. This method
## Documentation
- 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)
- 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).
@ -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).
❓ **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?**
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 });
}

View file

@ -0,0 +1,44 @@
self.MonacoEnvironment = {
getWorker: function (_moduleId, label) {
if (label === 'json') {
return new Worker(new URL('../../../src/language/json/json.worker.ts', import.meta.url), {
type: 'module'
});
}
if (label === 'css' || label === 'scss' || label === 'less') {
return new Worker(new URL('../../../src/language/css/css.worker.ts', import.meta.url), {
type: 'module'
});
}
if (label === 'html' || label === 'handlebars' || label === 'razor') {
return new Worker(new URL('../../../src/language/html/html.worker.ts', import.meta.url), {
type: 'module'
});
}
if (label === 'typescript' || label === 'javascript') {
return new Worker(new URL('../../../src/language/typescript/ts.worker.ts', import.meta.url), {
type: 'module'
});
}
return new Worker(new URL('../../../src/editor/editor.worker.ts', import.meta.url), {
type: 'module'
});
}
};
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';
import * as require_ from 'require';
const styleSheetUrl = require_.toUrl('vs/style.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({});
});
}
}

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

@ -0,0 +1,79 @@
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';
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;
}
return {
base: './',
define: {
AMD: false
},
build: {
lib: {
entry: {
...nlsEntries,
'nls.messages-loader': resolve(__dirname, 'src/nls.messages-loader.js'),
'editor/editor.main': resolve(__dirname, 'src/editor.main.js'),
'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: {}
},
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')
});
}
}
]
};
});

View file

@ -48,24 +48,6 @@ buildESM({
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
//#region html
@ -79,23 +61,6 @@ buildESM({
],
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
@ -110,23 +75,6 @@ buildESM({
],
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
@ -141,23 +89,6 @@ buildESM({
],
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
@ -191,23 +122,6 @@ glob('../src/basic-languages/*/*.contribution.ts', { cwd: __dirname }, function
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

View file

@ -16,15 +16,12 @@ import {
} from '../build/utils';
import { removeDir } from '../build/fs';
import { generateMetadata } from './releaseMetadata';
import { buildAmdMinDev } from './amd/build.script';
import ts = require('typescript');
removeDir(`out/monaco-editor`);
// // dev folder
// AMD_releaseOne('dev');
// // min folder
// AMD_releaseOne('min');
buildAmdMinDev();
// esm folder
ESM_release();
@ -56,11 +53,6 @@ generateMetadata();
otherFiles = otherFiles.concat(readFiles('README.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(
readFiles('node_modules/monaco-editor-core/LICENSE', {
base: 'node_modules/monaco-editor-core/'
@ -70,114 +62,6 @@ generateMetadata();
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() {
const coreFiles = readFiles(`node_modules/monaco-editor-core/esm/**/*`, {
base: 'node_modules/monaco-editor-core/esm',

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() {
const git = path.join(REPO_ROOT, '.git');
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>
```

View file

@ -68,8 +68,9 @@ async function prepareMonacoEditorRelease(monacoEditorCoreVersion: string) {
});
await group('Building & Testing', async () => {
//await run('npm run prettier-check', { cwd: rootPath });
await run('npm run build-monaco-editor', { 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 });

View file

@ -0,0 +1,11 @@
/*---------------------------------------------------------------------------------------------
* 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

@ -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

@ -8,6 +8,7 @@
"paths": {
"@/*": ["./*"]
},
"emitDeclarationOnly": true,
"strict": true,
"target": "es5",
"sourceMap": true,

View file

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

View file

@ -2,7 +2,7 @@
// 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')
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") } */
const tsvfs = globalThis.tsvfs;

View file

@ -6,6 +6,7 @@
<body>
<div id="editor-container" style="position: absolute; width: 500px; height: 400px"></div>
<script src="../../../out/monaco-editor/dev/vs/loader.js"></script>
<script>
require.config({
baseUrl: new URL('..', document.baseURI).toString(),
@ -13,8 +14,20 @@
vs: '../../../out/monaco-editor/dev/vs'
}
});
require.config({
'vs/nls': {
availableLanguages: {
'*': 'de'
}
}
});
require(['vs/editor/editor.main'], () => {
window.monacoAPI = monaco;
monaco.editor.create(document.getElementById('editor-container'), {
value: ['function x() {', '\tconsole.log("Hello world!");', '}'].join('\n'),
language: 'javascript'
});
});
</script>
</body>