build(site): [SITE-07] reproduce core outputs and validate localized editing

This commit is contained in:
Harvey Zhao committed 2026-09-15 11:02:31 +08:00
1 parent 244695e726
commit 0cfdf4a7e3
24 files changed
+10598 -5

No files matched your search

+2
View File
@@ -40,3 +40,5 @@ refactor/baselines/site-vendor/monaco-basic/** -text whitespace=-trailing-space,
refactor/baselines/monaco-basic-fixtures.json text eol=lf
refactor/baselines/site-vendor/monaco-core-origins/** -text whitespace=-trailing-space,cr-at-eol
docs/licenses/monaco-editor/core-origins/** -text whitespace=-trailing-space,cr-at-eol
refactor/baselines/site-vendor/monaco-core-build/** -text whitespace=-trailing-space,cr-at-eol
refactor/baselines/monaco-core-locales.json text eol=lf
+2 -1
View File
@@ -169,7 +169,8 @@
"verify:monaco-language-sources": "node scripts/site-vendor/monaco/reproduce-languages.ts",
"verify:monaco-mode-sources": "node scripts/site-vendor/monaco/reproduce-modes.ts",
"verify:monaco-basic-sources": "node scripts/site-vendor/monaco/reproduce-basic.ts",
"verify:monaco-core-origins": "node scripts/site-vendor/monaco/reproduce-core-origins.ts"
"verify:monaco-core-origins": "node scripts/site-vendor/monaco/reproduce-core-origins.ts",
"verify:monaco-core-build": "node scripts/site-vendor/monaco/reproduce-core-build.ts"
},
"browserslist": "last 1 Chrome version",
"devDependencies": {
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,72 @@
[
{
"locale": "en",
"find": "Find",
"next": "Next Match",
"close": "Close",
"member": "package/dev/vs/editor/editor.main.nls.js"
},
{
"locale": "de",
"find": "Suchen",
"next": "Nächste Übereinstimmung",
"close": "Schließen",
"member": "package/dev/vs/editor/editor.main.nls.de.js"
},
{
"locale": "es",
"find": "Buscar",
"next": "Coincidencia siguiente",
"close": "Cerrar",
"member": "package/dev/vs/editor/editor.main.nls.es.js"
},
{
"locale": "fr",
"find": "Rechercher",
"next": "Correspondance suivante",
"close": "Fermer",
"member": "package/dev/vs/editor/editor.main.nls.fr.js"
},
{
"locale": "it",
"find": "Trova",
"next": "Risultato successivo",
"close": "Chiudi",
"member": "package/dev/vs/editor/editor.main.nls.it.js"
},
{
"locale": "ja",
"find": "検索",
"next": "次の一致項目",
"close": "閉じる",
"member": "package/dev/vs/editor/editor.main.nls.ja.js"
},
{
"locale": "ko",
"find": "찾기",
"next": "다음 검색 결과",
"close": "닫기",
"member": "package/dev/vs/editor/editor.main.nls.ko.js"
},
{
"locale": "ru",
"find": "Найти",
"next": "Следующее совпадение",
"close": "Закрыть",
"member": "package/dev/vs/editor/editor.main.nls.ru.js"
},
{
"locale": "zh-cn",
"find": "查找",
"next": "下一个匹配项",
"close": "关闭",
"member": "package/dev/vs/editor/editor.main.nls.zh-cn.js"
},
{
"locale": "zh-tw",
"find": "尋找",
"next": "下一個相符項目",
"close": "關閉",
"member": "package/dev/vs/editor/editor.main.nls.zh-tw.js"
}
]
@@ -0,0 +1,481 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const gulp = require('gulp');
const path = require('path');
const util = require('./lib/util');
const task = require('./lib/task');
const common = require('./lib/optimize');
const es = require('event-stream');
const File = require('vinyl');
const i18n = require('./lib/i18n');
const standalone = require('./lib/standalone');
const cp = require('child_process');
const compilation = require('./lib/compilation');
const monacoapi = require('./lib/monaco-api');
const fs = require('fs');
let root = path.dirname(__dirname);
let sha1 = util.getVersion(root);
let semver = require('./monaco/package.json').version;
let headerVersion = semver + '(' + sha1 + ')';
// Build
let editorEntryPoints = [
{
name: 'vs/editor/editor.main',
include: [],
exclude: ['vs/css', 'vs/nls'],
prepend: ['out-editor-build/vs/css.js', 'out-editor-build/vs/nls.js'],
},
{
name: 'vs/base/common/worker/simpleWorker',
include: ['vs/editor/common/services/editorSimpleWorker'],
prepend: ['vs/loader.js'],
append: ['vs/base/worker/workerMain'],
dest: 'vs/base/worker/workerMain.js'
}
];
let editorResources = [
'out-editor-build/vs/base/browser/ui/codicons/**/*.ttf'
];
let BUNDLED_FILE_HEADER = [
'/*!-----------------------------------------------------------',
' * Copyright (c) Microsoft Corporation. All rights reserved.',
' * Version: ' + headerVersion,
' * Released under the MIT license',
' * https://github.com/microsoft/vscode/blob/main/LICENSE.txt',
' *-----------------------------------------------------------*/',
''
].join('\n');
const languages = i18n.defaultLanguages.concat([]); // i18n.defaultLanguages.concat(process.env.VSCODE_QUALITY !== 'stable' ? i18n.extraLanguages : []);
const extractEditorSrcTask = task.define('extract-editor-src', () => {
const apiusages = monacoapi.execute().usageContent;
const extrausages = fs.readFileSync(path.join(root, 'build', 'monaco', 'monaco.usage.recipe')).toString();
standalone.extractEditor({
sourcesRoot: path.join(root, 'src'),
entryPoints: [
'vs/editor/editor.main',
'vs/editor/editor.worker',
'vs/base/worker/workerMain',
],
inlineEntryPoints: [
apiusages,
extrausages
],
shakeLevel: 2, // 0-Files, 1-InnerFile, 2-ClassMembers
importIgnorePattern: /(^vs\/css!)/,
destRoot: path.join(root, 'out-editor-src'),
redirects: []
});
});
const compileEditorAMDTask = task.define('compile-editor-amd', compilation.compileTask('out-editor-src', 'out-editor-build', true));
const optimizeEditorAMDTask = task.define('optimize-editor-amd', common.optimizeTask({
src: 'out-editor-build',
entryPoints: editorEntryPoints,
resources: editorResources,
loaderConfig: {
paths: {
'vs': 'out-editor-build/vs',
'vs/css': 'out-editor-build/vs/css.build',
'vs/nls': 'out-editor-build/vs/nls.build',
'vscode': 'empty:'
}
},
bundleLoader: false,
header: BUNDLED_FILE_HEADER,
bundleInfo: true,
out: 'out-editor',
languages: languages
}));
const minifyEditorAMDTask = task.define('minify-editor-amd', common.minifyTask('out-editor'));
const createESMSourcesAndResourcesTask = task.define('extract-editor-esm', () => {
standalone.createESMSourcesAndResources2({
srcFolder: './out-editor-src',
outFolder: './out-editor-esm',
outResourcesFolder: './out-monaco-editor-core/esm',
ignores: [
'inlineEntryPoint:0.ts',
'inlineEntryPoint:1.ts',
'vs/loader.js',
'vs/nls.ts',
'vs/nls.build.js',
'vs/nls.d.ts',
'vs/css.js',
'vs/css.build.js',
'vs/css.d.ts',
'vs/base/worker/workerMain.ts',
],
renames: {
'vs/nls.mock.ts': 'vs/nls.ts'
}
});
});
const compileEditorESMTask = task.define('compile-editor-esm', () => {
const KEEP_PREV_ANALYSIS = false;
const FAIL_ON_PURPOSE = false;
console.log(`Launching the TS compiler at ${path.join(__dirname, '../out-editor-esm')}...`);
let result;
if (process.platform === 'win32') {
result = cp.spawnSync(`..\\node_modules\\.bin\\tsc.cmd`, {
cwd: path.join(__dirname, '../out-editor-esm')
});
} else {
result = cp.spawnSync(`node`, [`../node_modules/.bin/tsc`], {
cwd: path.join(__dirname, '../out-editor-esm')
});
}
console.log(result.stdout.toString());
console.log(result.stderr.toString());
if (FAIL_ON_PURPOSE || result.status !== 0) {
console.log(`The TS Compilation failed, preparing analysis folder...`);
const destPath = path.join(__dirname, '../../vscode-monaco-editor-esm-analysis');
const keepPrevAnalysis = (KEEP_PREV_ANALYSIS && fs.existsSync(destPath));
const cleanDestPath = (keepPrevAnalysis ? Promise.resolve() : util.rimraf(destPath)());
return cleanDestPath.then(() => {
// build a list of files to copy
const files = util.rreddir(path.join(__dirname, '../out-editor-esm'));
if (!keepPrevAnalysis) {
fs.mkdirSync(destPath);
// initialize a new repository
cp.spawnSync(`git`, [`init`], {
cwd: destPath
});
// copy files from src
for (const file of files) {
const srcFilePath = path.join(__dirname, '../src', file);
const dstFilePath = path.join(destPath, file);
if (fs.existsSync(srcFilePath)) {
util.ensureDir(path.dirname(dstFilePath));
const contents = fs.readFileSync(srcFilePath).toString().replace(/\r\n|\r|\n/g, '\n');
fs.writeFileSync(dstFilePath, contents);
}
}
// create an initial commit to diff against
cp.spawnSync(`git`, [`add`, `.`], {
cwd: destPath
});
// create the commit
cp.spawnSync(`git`, [`commit`, `-m`, `"original sources"`, `--no-gpg-sign`], {
cwd: destPath
});
}
// copy files from tree shaken src
for (const file of files) {
const srcFilePath = path.join(__dirname, '../out-editor-src', file);
const dstFilePath = path.join(destPath, file);
if (fs.existsSync(srcFilePath)) {
util.ensureDir(path.dirname(dstFilePath));
const contents = fs.readFileSync(srcFilePath).toString().replace(/\r\n|\r|\n/g, '\n');
fs.writeFileSync(dstFilePath, contents);
}
}
console.log(`Open in VS Code the folder at '${destPath}' and you can analyze the compilation error`);
throw new Error('Standalone Editor compilation failed. If this is the build machine, simply launch `yarn run gulp editor-distro` on your machine to further analyze the compilation problem.');
});
}
});
function toExternalDTS(contents) {
let lines = contents.split(/\r\n|\r|\n/);
let killNextCloseCurlyBrace = false;
for (let i = 0; i < lines.length; i++) {
let line = lines[i];
if (killNextCloseCurlyBrace) {
if ('}' === line) {
lines[i] = '';
killNextCloseCurlyBrace = false;
continue;
}
if (line.indexOf(' ') === 0) {
lines[i] = line.substr(4);
} else if (line.charAt(0) === '\t') {
lines[i] = line.substr(1);
}
continue;
}
if ('declare namespace monaco {' === line) {
lines[i] = '';
killNextCloseCurlyBrace = true;
continue;
}
if (line.indexOf('declare namespace monaco.') === 0) {
lines[i] = line.replace('declare namespace monaco.', 'export namespace ');
}
if (line.indexOf('declare let MonacoEnvironment') === 0) {
lines[i] = `declare global {\n let MonacoEnvironment: Environment | undefined;\n}`;
}
if (line.indexOf('\tMonacoEnvironment?') === 0) {
lines[i] = ` MonacoEnvironment?: Environment | undefined;`;
}
}
return lines.join('\n').replace(/\n\n\n+/g, '\n\n');
}
function filterStream(testFunc) {
return es.through(function (data) {
if (!testFunc(data.relative)) {
return;
}
this.emit('data', data);
});
}
const finalEditorResourcesTask = task.define('final-editor-resources', () => {
return es.merge(
// other assets
es.merge(
gulp.src('build/monaco/LICENSE'),
gulp.src('build/monaco/ThirdPartyNotices.txt'),
gulp.src('src/vs/monaco.d.ts')
).pipe(gulp.dest('out-monaco-editor-core')),
// place the .d.ts in the esm folder
gulp.src('src/vs/monaco.d.ts')
.pipe(es.through(function (data) {
this.emit('data', new File({
path: data.path.replace(/monaco\.d\.ts/, 'editor.api.d.ts'),
base: data.base,
contents: Buffer.from(toExternalDTS(data.contents.toString()))
}));
}))
.pipe(gulp.dest('out-monaco-editor-core/esm/vs/editor')),
// package.json
gulp.src('build/monaco/package.json')
.pipe(es.through(function (data) {
let json = JSON.parse(data.contents.toString());
json.private = false;
data.contents = Buffer.from(JSON.stringify(json, null, ' '));
this.emit('data', data);
}))
.pipe(gulp.dest('out-monaco-editor-core')),
// version.txt
gulp.src('build/monaco/version.txt')
.pipe(es.through(function (data) {
data.contents = Buffer.from(`monaco-editor-core: https://github.com/microsoft/vscode/tree/${sha1}`);
this.emit('data', data);
}))
.pipe(gulp.dest('out-monaco-editor-core')),
// README.md
gulp.src('build/monaco/README-npm.md')
.pipe(es.through(function (data) {
this.emit('data', new File({
path: data.path.replace(/README-npm\.md/, 'README.md'),
base: data.base,
contents: data.contents
}));
}))
.pipe(gulp.dest('out-monaco-editor-core')),
// dev folder
es.merge(
gulp.src('out-editor/**/*')
).pipe(gulp.dest('out-monaco-editor-core/dev')),
// min folder
es.merge(
gulp.src('out-editor-min/**/*')
).pipe(filterStream(function (path) {
// no map files
return !/(\.js\.map$)|(nls\.metadata\.json$)|(bundleInfo\.json$)/.test(path);
})).pipe(es.through(function (data) {
// tweak the sourceMappingURL
if (!/\.js$/.test(data.path)) {
this.emit('data', data);
return;
}
let relativePathToMap = path.relative(path.join(data.relative), path.join('min-maps', data.relative + '.map'));
let strContents = data.contents.toString();
let newStr = '//# sourceMappingURL=' + relativePathToMap.replace(/\\/g, '/');
strContents = strContents.replace(/\/\/# sourceMappingURL=[^ ]+$/, newStr);
data.contents = Buffer.from(strContents);
this.emit('data', data);
})).pipe(gulp.dest('out-monaco-editor-core/min')),
// min-maps folder
es.merge(
gulp.src('out-editor-min/**/*')
).pipe(filterStream(function (path) {
// no map files
return /\.js\.map$/.test(path);
})).pipe(gulp.dest('out-monaco-editor-core/min-maps'))
);
});
gulp.task('extract-editor-src',
task.series(
util.rimraf('out-editor-src'),
extractEditorSrcTask
)
);
gulp.task('editor-distro',
task.series(
task.parallel(
util.rimraf('out-editor-src'),
util.rimraf('out-editor-build'),
util.rimraf('out-editor-esm'),
util.rimraf('out-monaco-editor-core'),
util.rimraf('out-editor'),
util.rimraf('out-editor-min')
),
extractEditorSrcTask,
task.parallel(
task.series(
compileEditorAMDTask,
optimizeEditorAMDTask,
minifyEditorAMDTask
),
task.series(
createESMSourcesAndResourcesTask,
compileEditorESMTask
)
),
finalEditorResourcesTask
)
);
const bundleEditorESMTask = task.define('editor-esm-bundle-webpack', () => {
const webpack = require('webpack');
const webpackGulp = require('webpack-stream');
const result = es.through();
const webpackConfigPath = path.join(root, 'build/monaco/monaco.webpack.config.js');
const webpackConfig = {
...require(webpackConfigPath),
...{ mode: 'production' }
};
const webpackDone = (err, stats) => {
if (err) {
result.emit('error', err);
return;
}
const { compilation } = stats;
if (compilation.errors.length > 0) {
result.emit('error', compilation.errors.join('\n'));
}
if (compilation.warnings.length > 0) {
result.emit('data', compilation.warnings.join('\n'));
}
};
return webpackGulp(webpackConfig, webpack, webpackDone)
.pipe(gulp.dest('out-editor-esm-bundle'));
});
gulp.task('editor-esm-bundle',
task.series(
task.parallel(
util.rimraf('out-editor-src'),
util.rimraf('out-editor-esm'),
util.rimraf('out-monaco-editor-core'),
util.rimraf('out-editor-esm-bundle'),
),
extractEditorSrcTask,
createESMSourcesAndResourcesTask,
compileEditorESMTask,
bundleEditorESMTask,
)
);
gulp.task('monacodts', task.define('monacodts', () => {
const result = monacoapi.execute();
fs.writeFileSync(result.filePath, result.content);
fs.writeFileSync(path.join(root, 'src/vs/editor/common/standalone/standaloneEnums.ts'), result.enums);
return Promise.resolve(true);
}));
//#region monaco type checking
function createTscCompileTask(watch) {
return () => {
const createReporter = require('./lib/reporter').createReporter;
return new Promise((resolve, reject) => {
const args = ['./node_modules/.bin/tsc', '-p', './src/tsconfig.monaco.json', '--noEmit'];
if (watch) {
args.push('-w');
}
const child = cp.spawn(`node`, args, {
cwd: path.join(__dirname, '..'),
// stdio: [null, 'pipe', 'inherit']
});
let errors = [];
let reporter = createReporter('monaco');
let report;
// eslint-disable-next-line no-control-regex
let magic = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; // https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings
child.stdout.on('data', data => {
let str = String(data);
str = str.replace(magic, '').trim();
if (str.indexOf('Starting compilation') >= 0 || str.indexOf('File change detected') >= 0) {
errors.length = 0;
report = reporter.end(false);
} else if (str.indexOf('Compilation complete') >= 0) {
report.end();
} else if (str) {
let match = /(.*\(\d+,\d+\): )(.*: )(.*)/.exec(str);
if (match) {
// trying to massage the message so that it matches the gulp-tsb error messages
// e.g. src/vs/base/common/strings.ts(663,5): error TS2322: Type '1234' is not assignable to type 'string'.
let fullpath = path.join(root, match[1]);
let message = match[3];
reporter(fullpath + message);
} else {
reporter(str);
}
}
});
child.on('exit', resolve);
child.on('error', reject);
});
};
}
const monacoTypecheckWatchTask = task.define('monaco-typecheck-watch', createTscCompileTask(true));
exports.monacoTypecheckWatchTask = monacoTypecheckWatchTask;
const monacoTypecheckTask = task.define('monaco-typecheck', createTscCompileTask(false));
exports.monacoTypecheckTask = monacoTypecheckTask;
//#endregion
@@ -0,0 +1,302 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as es from 'event-stream';
import * as gulp from 'gulp';
import * as concat from 'gulp-concat';
import * as filter from 'gulp-filter';
import * as fancyLog from 'fancy-log';
import * as ansiColors from 'ansi-colors';
import * as path from 'path';
import * as pump from 'pump';
import * as VinylFile from 'vinyl';
import * as bundle from './bundle';
import { Language, processNlsFiles } from './i18n';
import { createStatsStream } from './stats';
import * as util from './util';
const REPO_ROOT_PATH = path.join(__dirname, '../..');
function log(prefix: string, message: string): void {
fancyLog(ansiColors.cyan('[' + prefix + ']'), message);
}
export function loaderConfig() {
const result: any = {
paths: {
'vs': 'out-build/vs',
'vscode': 'empty:'
},
amdModulesPattern: /^vs\//
};
result['vs/css'] = { inlineResources: true };
return result;
}
const IS_OUR_COPYRIGHT_REGEXP = /Copyright \(C\) Microsoft Corporation/i;
function loader(src: string, bundledFileHeader: string, bundleLoader: boolean, externalLoaderInfo?: any): NodeJS.ReadWriteStream {
let sources = [
`${src}/vs/loader.js`
];
if (bundleLoader) {
sources = sources.concat([
`${src}/vs/css.js`,
`${src}/vs/nls.js`
]);
}
let isFirst = true;
return (
gulp
.src(sources, { base: `${src}` })
.pipe(es.through(function (data) {
if (isFirst) {
isFirst = false;
this.emit('data', new VinylFile({
path: 'fake',
base: '.',
contents: Buffer.from(bundledFileHeader)
}));
this.emit('data', data);
} else {
this.emit('data', data);
}
}, function () {
if (externalLoaderInfo !== undefined) {
this.emit('data', new VinylFile({
path: 'fake2',
base: '.',
contents: Buffer.from(`require.config(${JSON.stringify(externalLoaderInfo, undefined, 2)});`)
}));
}
this.emit('end');
}))
.pipe(concat('vs/loader.js'))
);
}
function toConcatStream(src: string, bundledFileHeader: string, sources: bundle.IFile[], dest: string, fileContentMapper: (contents: string, path: string) => string): NodeJS.ReadWriteStream {
const useSourcemaps = /\.js$/.test(dest) && !/\.nls\.js$/.test(dest);
// If a bundle ends up including in any of the sources our copyright, then
// insert a fake source at the beginning of each bundle with our copyright
let containsOurCopyright = false;
for (let i = 0, len = sources.length; i < len; i++) {
const fileContents = sources[i].contents;
if (IS_OUR_COPYRIGHT_REGEXP.test(fileContents)) {
containsOurCopyright = true;
break;
}
}
if (containsOurCopyright) {
sources.unshift({
path: null,
contents: bundledFileHeader
});
}
const treatedSources = sources.map(function (source) {
const root = source.path ? REPO_ROOT_PATH.replace(/\\/g, '/') : '';
const base = source.path ? root + `/${src}` : '.';
const path = source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake';
const contents = source.path ? fileContentMapper(source.contents, path) : source.contents;
return new VinylFile({
path: path,
base: base,
contents: Buffer.from(contents)
});
});
return es.readArray(treatedSources)
.pipe(useSourcemaps ? util.loadSourcemaps() : es.through())
.pipe(concat(dest))
.pipe(createStatsStream(dest));
}
function toBundleStream(src: string, bundledFileHeader: string, bundles: bundle.IConcatFile[], fileContentMapper: (contents: string, path: string) => string): NodeJS.ReadWriteStream {
return es.merge(bundles.map(function (bundle) {
return toConcatStream(src, bundledFileHeader, bundle.sources, bundle.dest, fileContentMapper);
}));
}
export interface IOptimizeTaskOpts {
/**
* The folder to read files from.
*/
src: string;
/**
* (for AMD files, will get bundled and get Copyright treatment)
*/
entryPoints: bundle.IEntryPoint[];
/**
* (svg, etc.)
*/
resources: string[];
loaderConfig: any;
/**
* Additional info we append to the end of the loader
*/
externalLoaderInfo?: any;
/**
* (true by default - append css and nls to loader)
*/
bundleLoader?: boolean;
/**
* (basically the Copyright treatment)
*/
header?: string;
/**
* (emit bundleInfo.json file)
*/
bundleInfo: boolean;
/**
* (out folder name)
*/
out: string;
/**
* (out folder name)
*/
languages?: Language[];
/**
* File contents interceptor
* @param contents The contens of the file
* @param path The absolute file path, always using `/`, even on Windows
*/
fileContentMapper?: (contents: string, path: string) => string;
}
const DEFAULT_FILE_HEADER = [
'/*!--------------------------------------------------------',
' * Copyright (C) Microsoft Corporation. All rights reserved.',
' *--------------------------------------------------------*/'
].join('\n');
export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStream {
const src = opts.src;
const entryPoints = opts.entryPoints;
const resources = opts.resources;
const loaderConfig = opts.loaderConfig;
const bundledFileHeader = opts.header || DEFAULT_FILE_HEADER;
const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader);
const out = opts.out;
const fileContentMapper = opts.fileContentMapper || ((contents: string, _path: string) => contents);
return function () {
const sourcemaps = require('gulp-sourcemaps') as typeof import('gulp-sourcemaps');
const bundlesStream = es.through(); // this stream will contain the bundled files
const resourcesStream = es.through(); // this stream will contain the resources
const bundleInfoStream = es.through(); // this stream will contain bundleInfo.json
bundle.bundle(entryPoints, loaderConfig, function (err, result) {
if (err || !result) { return bundlesStream.emit('error', JSON.stringify(err)); }
toBundleStream(src, bundledFileHeader, result.files, fileContentMapper).pipe(bundlesStream);
// Remove css inlined resources
const filteredResources = resources.slice();
result.cssInlinedResources.forEach(function (resource) {
if (process.env['VSCODE_BUILD_VERBOSE']) {
log('optimizer', 'excluding inlined: ' + resource);
}
filteredResources.push('!' + resource);
});
gulp.src(filteredResources, { base: `${src}`, allowEmpty: true }).pipe(resourcesStream);
const bundleInfoArray: VinylFile[] = [];
if (opts.bundleInfo) {
bundleInfoArray.push(new VinylFile({
path: 'bundleInfo.json',
base: '.',
contents: Buffer.from(JSON.stringify(result.bundleData, null, '\t'))
}));
}
es.readArray(bundleInfoArray).pipe(bundleInfoStream);
});
const result = es.merge(
loader(src, bundledFileHeader, bundleLoader, opts.externalLoaderInfo),
bundlesStream,
resourcesStream,
bundleInfoStream
);
return result
.pipe(sourcemaps.write('./', {
sourceRoot: undefined,
addComment: true,
includeContent: true
}))
.pipe(opts.languages && opts.languages.length ? processNlsFiles({
fileHeader: bundledFileHeader,
languages: opts.languages
}) : es.through())
.pipe(gulp.dest(out));
};
}
export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) => void {
const esbuild = require('esbuild') as typeof import('esbuild');
const sourceMappingURL = sourceMapBaseUrl ? ((f: any) => `${sourceMapBaseUrl}/${f.relative}.map`) : undefined;
return cb => {
const cssnano = require('cssnano') as typeof import('cssnano');
const postcss = require('gulp-postcss') as typeof import('gulp-postcss');
const sourcemaps = require('gulp-sourcemaps') as typeof import('gulp-sourcemaps');
const jsFilter = filter('**/*.js', { restore: true });
const cssFilter = filter('**/*.css', { restore: true });
pump(
gulp.src([src + '/**', '!' + src + '/**/*.map']),
jsFilter,
sourcemaps.init({ loadMaps: true }),
es.map((f: any, cb) => {
esbuild.build({
entryPoints: [f.path],
minify: true,
sourcemap: 'external',
outdir: '.',
platform: 'node',
target: ['esnext'],
write: false
}).then(res => {
const jsFile = res.outputFiles.find(f => /\.js$/.test(f.path))!;
const sourceMapFile = res.outputFiles.find(f => /\.js\.map$/.test(f.path))!;
f.contents = Buffer.from(jsFile.contents);
f.sourceMap = JSON.parse(sourceMapFile.text);
cb(undefined, f);
}, cb);
}),
jsFilter.restore,
cssFilter,
postcss([cssnano({ preset: 'default' })]),
cssFilter.restore,
(<any>sourcemaps).mapSources((sourcePath: string) => {
if (sourcePath === 'bootstrap-fork.js') {
return 'bootstrap-fork.orig.js';
}
return sourcePath;
}),
sourcemaps.write('./', {
sourceMappingURL,
sourceRoot: undefined,
includeContent: true,
addComment: true
} as any),
gulp.dest(src + '-min'),
(err: any) => cb(err));
};
}
@@ -0,0 +1,75 @@
{
"name": "code-oss-dev-build",
"version": "1.0.0",
"license": "MIT",
"devDependencies": {
"@azure/cosmos": "^3.9.3",
"@azure/storage-blob": "^12.4.0",
"@electron/get": "^1.12.4",
"@types/ansi-colors": "^3.2.0",
"@types/azure": "0.9.19",
"@types/byline": "^4.2.32",
"@types/cssnano": "^4.0.0",
"@types/debounce": "^1.0.0",
"@types/eslint": "4.16.1",
"@types/fancy-log": "^1.3.0",
"@types/fs-extra": "^9.0.12",
"@types/glob": "^7.1.1",
"@types/gulp": "^4.0.5",
"@types/gulp-concat": "^0.0.32",
"@types/gulp-filter": "^3.0.32",
"@types/gulp-gzip": "^0.0.31",
"@types/gulp-json-editor": "^2.2.31",
"@types/gulp-postcss": "^8.0.0",
"@types/gulp-rename": "^0.0.33",
"@types/gulp-sourcemaps": "^0.0.32",
"@types/mime": "0.0.29",
"@types/minimatch": "^3.0.3",
"@types/minimist": "^1.2.1",
"@types/mkdirp": "^1.0.1",
"@types/mocha": "^8.2.0",
"@types/node": "14.x",
"@types/p-limit": "^2.2.0",
"@types/plist": "^3.0.2",
"@types/pump": "^1.0.1",
"@types/request": "^2.47.0",
"@types/rimraf": "^2.0.4",
"@types/through": "^0.0.29",
"@types/through2": "^2.0.34",
"@types/tmp": "^0.2.1",
"@types/underscore": "^1.8.9",
"@types/webpack": "^4.41.25",
"@types/xml2js": "0.0.33",
"@typescript-eslint/experimental-utils": "~2.13.0",
"@typescript-eslint/parser": "^3.3.0",
"applicationinsights": "1.0.8",
"azure-storage": "^2.1.0",
"byline": "^5.0.0",
"colors": "^1.4.0",
"commander": "^7.0.0",
"debug": "^4.3.2",
"electron-osx-sign": "^0.4.16",
"esbuild": "^0.12.6",
"extract-zip": "^2.0.1",
"fs-extra": "^9.1.0",
"got": "11.8.1",
"gulp-merge-json": "^2.1.1",
"iconv-lite-umd": "0.6.8",
"jsonc-parser": "^2.3.0",
"mime": "^1.4.1",
"mkdirp": "^1.0.4",
"p-limit": "^3.1.0",
"plist": "^3.0.1",
"source-map": "0.6.1",
"tmp": "^0.2.1",
"typescript": "^4.5.0-dev.20211021",
"vsce": "^1.100.0",
"vscode-universal-bundler": "^0.0.2"
},
"scripts": {
"compile": "tsc -p tsconfig.build.json",
"watch": "tsc -p tsconfig.build.json --watch",
"npmCheckJs": "tsc --noEmit"
},
"dependencies": {}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,115 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
* Please make sure to make edits in the .ts file at https://github.com/microsoft/vscode-loader/
*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
*--------------------------------------------------------------------------------------------*/
'use strict';
var CSSLoaderPlugin;
(function (CSSLoaderPlugin) {
/**
* Known issue:
* - In IE there is no way to know if the CSS file loaded successfully or not.
*/
var BrowserCSSLoader = /** @class */ (function () {
function BrowserCSSLoader() {
this._pendingLoads = 0;
}
BrowserCSSLoader.prototype.attachListeners = function (name, linkNode, callback, errorback) {
var unbind = function () {
linkNode.removeEventListener('load', loadEventListener);
linkNode.removeEventListener('error', errorEventListener);
};
var loadEventListener = function (e) {
unbind();
callback();
};
var errorEventListener = function (e) {
unbind();
errorback(e);
};
linkNode.addEventListener('load', loadEventListener);
linkNode.addEventListener('error', errorEventListener);
};
BrowserCSSLoader.prototype._onLoad = function (name, callback) {
this._pendingLoads--;
callback();
};
BrowserCSSLoader.prototype._onLoadError = function (name, errorback, err) {
this._pendingLoads--;
errorback(err);
};
BrowserCSSLoader.prototype._insertLinkNode = function (linkNode) {
this._pendingLoads++;
var head = document.head || document.getElementsByTagName('head')[0];
head.appendChild(linkNode);
};
BrowserCSSLoader.prototype.createLinkTag = function (name, cssUrl, externalCallback, externalErrorback) {
var _this = this;
var linkNode = document.createElement('link');
linkNode.setAttribute('rel', 'stylesheet');
linkNode.setAttribute('type', 'text/css');
linkNode.setAttribute('data-name', name);
var callback = function () { return _this._onLoad(name, externalCallback); };
var errorback = function (err) { return _this._onLoadError(name, externalErrorback, err); };
this.attachListeners(name, linkNode, callback, errorback);
linkNode.setAttribute('href', cssUrl);
return linkNode;
};
BrowserCSSLoader.prototype._linkTagExists = function (name, cssUrl) {
var i, len, nameAttr, hrefAttr, links = document.getElementsByTagName('link');
for (i = 0, len = links.length; i < len; i++) {
nameAttr = links[i].getAttribute('data-name');
hrefAttr = links[i].getAttribute('href');
if (nameAttr === name || hrefAttr === cssUrl) {
return true;
}
}
return false;
};
BrowserCSSLoader.prototype.load = function (name, cssUrl, externalCallback, externalErrorback) {
if (this._linkTagExists(name, cssUrl)) {
externalCallback();
return;
}
var linkNode = this.createLinkTag(name, cssUrl, externalCallback, externalErrorback);
this._insertLinkNode(linkNode);
};
return BrowserCSSLoader;
}());
// ------------------------------ Finally, the plugin
var CSSPlugin = /** @class */ (function () {
function CSSPlugin() {
this._cssLoader = new BrowserCSSLoader();
}
CSSPlugin.prototype.load = function (name, req, load, config) {
config = config || {};
var cssConfig = config['vs/css'] || {};
if (cssConfig.disabled) {
// the plugin is asked to not create any style sheets
load({});
return;
}
var cssUrl = req.toUrl(name + '.css');
this._cssLoader.load(name, cssUrl, function (contents) {
load({});
}, function (err) {
if (typeof load.error === 'function') {
load.error('Could not find ' + cssUrl + ' or it was empty');
}
});
};
return CSSPlugin;
}());
CSSLoaderPlugin.CSSPlugin = CSSPlugin;
define('vs/css', new CSSPlugin());
})(CSSLoaderPlugin || (CSSLoaderPlugin = {}));
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,160 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
* Please make sure to make edits in the .ts file at https://github.com/microsoft/vscode-loader/
*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
*---------------------------------------------------------------------------------------------
*--------------------------------------------------------------------------------------------*/
'use strict';
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
var NLSLoaderPlugin;
(function (NLSLoaderPlugin) {
var Environment = /** @class */ (function () {
function Environment() {
this._detected = false;
this._isPseudo = false;
}
Object.defineProperty(Environment.prototype, "isPseudo", {
get: function () {
this._detect();
return this._isPseudo;
},
enumerable: false,
configurable: true
});
Environment.prototype._detect = function () {
if (this._detected) {
return;
}
this._detected = true;
this._isPseudo = (typeof document !== 'undefined' && document.location && document.location.hash.indexOf('pseudo=true') >= 0);
};
return Environment;
}());
function _format(message, args, env) {
var result;
if (args.length === 0) {
result = message;
}
else {
result = message.replace(/\{(\d+)\}/g, function (match, rest) {
var index = rest[0];
var arg = args[index];
var result = match;
if (typeof arg === 'string') {
result = arg;
}
else if (typeof arg === 'number' || typeof arg === 'boolean' || arg === void 0 || arg === null) {
result = String(arg);
}
return result;
});
}
if (env.isPseudo) {
// FF3B and FF3D is the Unicode zenkaku representation for [ and ]
result = '\uFF3B' + result.replace(/[aouei]/g, '$&$&') + '\uFF3D';
}
return result;
}
function findLanguageForModule(config, name) {
var result = config[name];
if (result)
return result;
result = config['*'];
if (result)
return result;
return null;
}
function localize(env, data, message) {
var args = [];
for (var _i = 3; _i < arguments.length; _i++) {
args[_i - 3] = arguments[_i];
}
return _format(message, args, env);
}
function createScopedLocalize(scope, env) {
return function (idx, defaultValue) {
var restArgs = Array.prototype.slice.call(arguments, 2);
return _format(scope[idx], restArgs, env);
};
}
var NLSPlugin = /** @class */ (function () {
function NLSPlugin(env) {
var _this = this;
this._env = env;
this.localize = function (data, message) {
var args = [];
for (var _i = 2; _i < arguments.length; _i++) {
args[_i - 2] = arguments[_i];
}
return localize.apply(void 0, __spreadArrays([_this._env, data, message], args));
};
}
NLSPlugin.prototype.setPseudoTranslation = function (value) {
this._env._isPseudo = value;
};
NLSPlugin.prototype.create = function (key, data) {
return {
localize: createScopedLocalize(data[key], this._env)
};
};
NLSPlugin.prototype.load = function (name, req, load, config) {
var _this = this;
config = config || {};
if (!name || name.length === 0) {
load({
localize: this.localize
});
}
else {
var pluginConfig = config['vs/nls'] || {};
var language = pluginConfig.availableLanguages ? findLanguageForModule(pluginConfig.availableLanguages, name) : null;
var suffix = '.nls';
if (language !== null && language !== NLSPlugin.DEFAULT_TAG) {
suffix = suffix + '.' + language;
}
var messagesLoaded_1 = function (messages) {
if (Array.isArray(messages)) {
messages.localize = createScopedLocalize(messages, _this._env);
}
else {
messages.localize = createScopedLocalize(messages[name], _this._env);
}
load(messages);
};
if (typeof pluginConfig.loadBundle === 'function') {
pluginConfig.loadBundle(name, language, function (err, messages) {
// We have an error. Load the English default strings to not fail
if (err) {
req([name + '.nls'], messagesLoaded_1);
}
else {
messagesLoaded_1(messages);
}
});
}
else {
req([name + suffix], messagesLoaded_1);
}
}
};
NLSPlugin.DEFAULT_TAG = 'i-default';
return NLSPlugin;
}());
NLSLoaderPlugin.NLSPlugin = NLSPlugin;
define('vs/nls', new NLSPlugin(new Environment()));
})(NLSLoaderPlugin || (NLSLoaderPlugin = {}));
@@ -0,0 +1,47 @@
# SITE-07 Monaco 核心压缩、加载器与十语言编辑回归
修改前 HEAD:244695e7262902c59b522b0a72543f787a442afd。
## 本批实现
固定 VS Code 配方/锁文件确认 core 0.30.1 使用 esbuild 0.12.6。新增独立
reproduce-core-build.ts,校验 Monaco/core/历史 esbuild 归档和七个 Git 文件,
直接从平台归档读取已校验的可执行文件;不执行安装脚本、不改根依赖或 yarn.lock。
记录 Windows/Linux x64 两种归档,实际执行证据仅覆盖 Windows x64。
13 个 core JS 文件(editor、worker、loader、英文及九份翻译)的完整压缩字节
均复现。保留 node/esnext/minify 原参数,准确恢复 source-map 注释前的额外换行
及相对路径,没有用 trim 忽略差异。12 个文件直接匹配站点;editor.main 核心
部分保留原入口改名和追加贡献模块边界,不把该边界检查称为完整后缀重建。
loader 原始 Git 源码及版本头精确匹配,css/nls loader 固定源码与 source map
一致。两个原始 source map 的 584 个条目、549 个不同源码名逐项登记内容哈希
和字节数。这些是上游准备后的构建输入,不是完整 VS Code 原始 TS 编译证明。
core-build.ts 将 NLS 静态解析、source map 清单和末尾注释装配分开。原 NLS
包含尾逗号,所以用 TS AST 读取字面量数组;不执行翻译脚本,拒绝动态调用、
重复键或额外语句。十种语言查找文案从原归档解析后冻结为浏览器输入,完整
复验会重新读取并比较。新命令 yarn verify:monaco-core-build 支持 --fetch。
## 浏览器与其他验证
editor-core.spec.js 每种语言执行真实键盘输入、撤销、重做,打开本地化查找框,
等待新查询对应的实际选择范围后跳到下一项,退出并销毁 editor/model。
初始测试用了不存在的旧 CSS 组合,页面快照表明查找框已经显示;改成实际
可访问名称。又修正了旧选区先于查询更新的测试竞态,未增加任意等待或改运行代码。
十种语言在三引擎 30/30 通过,另一个真实 diff worker 用例三引擎 3/3 通过:
第二行变更被计算出来、输入改成相同内容后差异清空、模型全部释放。
单元 20/20、严格 docs-tools 类型与本批 lint 通过。归档/Git 联网复验与离线
复验通过,13 个压缩产物相等。环境、输出指纹和两次浏览器报告见
[验证记录](../baselines/monaco-core-build-validation.json)。未改变运行资产或许可
交付,本批没有重复声称播放器/设备/SDK/远程 CI 验收。
## 后续与范围
维护入口:[Monaco README](../../scripts/site-vendor/monaco/README.md)。继续 core
贡献模块装配、CSS 以及已定位的来源边界:Node path、WinJS 适配、unicode-utils
生成数据、HSL 公式引用和 marked 的 Stack Overflow 片段。引用不自动等于许可
缺口,后续需按实际表达和来源确认。本批没有替这些条目作完结判断。
SITE-07 doing / VENDOR-06 open,199/265;Thumbnail 默认策略仍待用户答复。
可独立回退新增脚本、基线和测试。独立本地提交,不推送、部署或发布。
+1 -1
View File
@@ -653,7 +653,7 @@
- SITE-AI-DOCS-01: [记录](changes/2026-09-14-SITE-AI-DOCS-01-documentation-pipeline.md) [记录](baselines/documentation-pipeline-validation.json)
- SITE-BUILD-01: [记录](changes/2026-09-14-SITE-BUILD-01-staged-builds.md) [记录](baselines/site-build-validation.json)
- SITE-03: [记录](changes/2026-09-14-SITE-03-desktop-editor.md) [记录](baselines/site-editor-validation.json)
- SITE-07: [记录](site-inventory.md) [记录](baselines/site-provenance.json) [记录](changes/2026-09-14-SITE-07-vendor-notices.md) [记录](baselines/site-notices-checkpoint.json) [记录](baselines/site-codicons-provenance.json) [记录](baselines/site-codicons-validation.json) [记录](changes/2026-09-15-SITE-07-codicons.md) [记录](baselines/vconsole-notices-provenance.json) [记录](baselines/vconsole-notices-validation.json) [记录](changes/2026-09-15-SITE-07-vconsole-notices.md) [记录](console-modernization.md) [记录](baselines/site-console-inventory.json) [记录](baselines/site-console-validation.json) [记录](changes/2026-09-15-SITE-07-console-baseline.md) [记录](baselines/console-feed-provenance.json) [记录](changes/2026-09-15-SITE-07-console-feed-source.md) [记录](baselines/console-commonjs-provenance.json) [记录](changes/2026-09-15-SITE-07-console-commonjs.md) [记录](baselines/console-esm-provenance.json) [记录](changes/2026-09-15-SITE-07-console-esm.md) [记录](baselines/console-embedded-notices.json) [记录](baselines/console-notices-validation.json) [记录](changes/2026-09-15-SITE-07-console-notices.md) [记录](baselines/console-embedded-sources.json) [记录](baselines/console-embedded-validation.json) [记录](changes/2026-09-15-SITE-07-console-embedded-sources.md) [记录](baselines/console-derived-attribution.json) [记录](baselines/console-derived-validation.json) [记录](changes/2026-09-15-SITE-07-console-derived-attribution.md) [记录](baselines/console-stackoverflow-provenance.json) [记录](baselines/console-stackoverflow-validation.json) [记录](changes/2026-09-15-SITE-07-console-stackoverflow.md) [记录](baselines/console-shallowequal-validation.json) [记录](changes/2026-09-15-SITE-07-console-shallowequal.md) [记录](console-notice-review.md) [记录](baselines/console-notice-review-validation.json) [记录](changes/2026-09-15-SITE-07-console-notice-review.md) [记录](baselines/monaco-typescript-provenance.json) [记录](baselines/monaco-typescript-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-typescript.md) [记录](baselines/monaco-languages-provenance.json) [记录](baselines/monaco-languages-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-languages.md) [记录](baselines/monaco-language-notices.json) [记录](baselines/monaco-language-notices-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-language-notices.md) [记录](baselines/monaco-modes-provenance.json) [记录](baselines/monaco-modes-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-modes.md) [记录](baselines/monaco-basic-provenance.json) [记录](baselines/monaco-basic-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-basic.md) [记录](baselines/monaco-core-origins-provenance.json) [记录](baselines/monaco-core-origins-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-core-origins.md)
- SITE-07: [记录](site-inventory.md) [记录](baselines/site-provenance.json) [记录](changes/2026-09-14-SITE-07-vendor-notices.md) [记录](baselines/site-notices-checkpoint.json) [记录](baselines/site-codicons-provenance.json) [记录](baselines/site-codicons-validation.json) [记录](changes/2026-09-15-SITE-07-codicons.md) [记录](baselines/vconsole-notices-provenance.json) [记录](baselines/vconsole-notices-validation.json) [记录](changes/2026-09-15-SITE-07-vconsole-notices.md) [记录](console-modernization.md) [记录](baselines/site-console-inventory.json) [记录](baselines/site-console-validation.json) [记录](changes/2026-09-15-SITE-07-console-baseline.md) [记录](baselines/console-feed-provenance.json) [记录](changes/2026-09-15-SITE-07-console-feed-source.md) [记录](baselines/console-commonjs-provenance.json) [记录](changes/2026-09-15-SITE-07-console-commonjs.md) [记录](baselines/console-esm-provenance.json) [记录](changes/2026-09-15-SITE-07-console-esm.md) [记录](baselines/console-embedded-notices.json) [记录](baselines/console-notices-validation.json) [记录](changes/2026-09-15-SITE-07-console-notices.md) [记录](baselines/console-embedded-sources.json) [记录](baselines/console-embedded-validation.json) [记录](changes/2026-09-15-SITE-07-console-embedded-sources.md) [记录](baselines/console-derived-attribution.json) [记录](baselines/console-derived-validation.json) [记录](changes/2026-09-15-SITE-07-console-derived-attribution.md) [记录](baselines/console-stackoverflow-provenance.json) [记录](baselines/console-stackoverflow-validation.json) [记录](changes/2026-09-15-SITE-07-console-stackoverflow.md) [记录](baselines/console-shallowequal-validation.json) [记录](changes/2026-09-15-SITE-07-console-shallowequal.md) [记录](console-notice-review.md) [记录](baselines/console-notice-review-validation.json) [记录](changes/2026-09-15-SITE-07-console-notice-review.md) [记录](baselines/monaco-typescript-provenance.json) [记录](baselines/monaco-typescript-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-typescript.md) [记录](baselines/monaco-languages-provenance.json) [记录](baselines/monaco-languages-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-languages.md) [记录](baselines/monaco-language-notices.json) [记录](baselines/monaco-language-notices-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-language-notices.md) [记录](baselines/monaco-modes-provenance.json) [记录](baselines/monaco-modes-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-modes.md) [记录](baselines/monaco-basic-provenance.json) [记录](baselines/monaco-basic-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-basic.md) [记录](baselines/monaco-core-origins-provenance.json) [记录](baselines/monaco-core-origins-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-core-origins.md) [记录](baselines/monaco-core-build-provenance.json) [记录](baselines/monaco-core-build-validation.json) [记录](changes/2026-09-15-SITE-07-monaco-core-build.md)
- EX-01: [记录](changes/2026-09-14-EX-01-react-consumer.md) [记录](baselines/react-consumer-validation.json) [记录](scripts/react-consumer.mjs)
- EX-02: [记录](changes/2026-09-14-EX-02-vue-consumer.md) [记录](baselines/vue-consumer-validation.json) [记录](scripts/vue-consumer.mjs)
- MOD-01: [记录](changes/2026-09-15-MOD-01-bun-evaluation.md) [记录](baselines/bun-install-validation.json) [记录](bun-evaluation.md)
+9
View File
@@ -1,5 +1,14 @@
# 进度与证据
## SITE-07 Monaco 核心压缩与编辑操作
固定 esbuild 0.12.6 精确复现 13 个 core JS 产物,loader 源码/版本头及 css/nls
loader 来源匹配;两个 map 登记 584 条目、549 个不同准备源码。十语言真实编辑/
撤销重做/查找/销毁 30/30,diff worker 3/3,单元 20/20、类型/lint、联网/离线
来源检查通过。见[记录](changes/2026-09-15-SITE-07-monaco-core-build.md)。完整原始
TS 编译与余下内嵌来源未被这些检查替代,SITE-07/VENDOR-06 开放、199/265。
后续 core 贡献装配/CSS/已定位来源边界;Thumbnail 默认策略仍待答。
## SITE-07 Monaco Markdown 来源与遗漏许可
核实 DOMPurify 2.3.1 / marked 3.0.2 的固定来源及完整模块适配,发现并补齐
+5 -2
View File
@@ -649,11 +649,14 @@
"refactor/changes/2026-09-15-SITE-07-monaco-basic.md",
"refactor/baselines/monaco-core-origins-provenance.json",
"refactor/baselines/monaco-core-origins-validation.json",
"refactor/changes/2026-09-15-SITE-07-monaco-core-origins.md"
"refactor/changes/2026-09-15-SITE-07-monaco-core-origins.md",
"refactor/baselines/monaco-core-build-provenance.json",
"refactor/baselines/monaco-core-build-validation.json",
"refactor/changes/2026-09-15-SITE-07-monaco-core-build.md"
],
"compatibleResolution": "Keep separate from owned TS migration. Verify source/version/diff and license notices before replacement; preserve API/CSS/worker URLs and run owning package tests.",
"closureCriteria": "固定上游版本/内容差异、完整组件许可与分发 notices,兼容测试通过;仅当前上游许可证名称不足以关闭。",
"workspaceState": "Monaco 0.30.1 remains byte-pinned (the known CSS newline-only difference is preserved). Codicons 0.0.26 and the actual TypeScript 4.4.4 worker have original notice supplements. CSS/HTML/JSON workers, four mode bundles and all 76 basic-language bundles reproduce exactly; 2511 upstream plus 12 supplemental tokenizer cases pass in three engines. DOMPurify 2.3.1 and marked 3.0.2 now have exact npm-to-Git/source-map/development adaptations; the missing DOMPurify terms and original/legacy marked licenses are delivered. All 85 site notices and attribution links pass three-engine HTTP/mobile playback checks; Markdown formatting/filtering/hook cleanup also passes. Latest unit 18/18, strict type/lint and four-archive/seven-Git offline/network checks pass. The complete core compiler pipeline, other core/loader/localization and further embedded origins remain open; this is not an exhaustive sanitizer audit or release approval."
"workspaceState": "Monaco 0.30.1 remains byte-pinned (the known CSS newline-only difference is preserved). Codicons 0.0.26 and the actual TypeScript 4.4.4 worker have original notice supplements. CSS/HTML/JSON workers, four mode bundles and all 76 basic-language bundles reproduce exactly; 2511 upstream plus 12 supplemental tokenizer cases pass in three engines. DOMPurify 2.3.1 and marked 3.0.2 now have exact npm-to-Git/source-map/development adaptations; the missing DOMPurify terms and original/legacy marked licenses are delivered. All 85 site notices and attribution links pass three-engine HTTP/mobile playback checks; Markdown formatting/filtering/hook cleanup also passes. Latest unit 18/18, strict type/lint and four-archive/seven-Git offline/network checks pass. The complete core compiler pipeline, other core/loader/localization and further embedded origins remain open; this is not an exhaustive sanitizer audit or release approval. All 13 core JavaScript minified outputs now reproduce with locked esbuild 0.12.6 on Windows x64; loader source/header and css/nls sources match fixed Git. Two maps inventory 584 prepared-source entries with 549 different names. Ten-locale editing/find checks pass 30/30 and core diff-worker checks pass 3/3; unit 20/20, type/lint and offline/network checks pass. Complete original TS compilation, appended contributions, CSS and remaining embedded origins are not claimed complete."
},
{
"id": "VENDOR-07",
+5
View File
@@ -1,5 +1,10 @@
# 文档站、示例与生成链清单
核心分发后续:13 个 core JavaScript 压缩产物已通过固定 esbuild 0.12.6 精确
复现,loader 与 css/nls loader 固定源码匹配;十种语言编辑/查找和核心 diff
worker 三引擎 33/33 通过。两个 source map 的 549 份不同准备源码已登记,
后续来源边界与完整编译限制见[记录](changes/2026-09-15-SITE-07-monaco-core-build.md)。
当前补充:Monaco 四种 mode 与 76 种基础语言的完整产物复现、三引擎语法验证
已完成。核心 Markdown 内嵌 DOMPurify 2.3.1 / marked 3.0.2 的固定来源和模块
适配已匹配;补齐四份说明后站点共交付 85 份 notice。核心其余源码与内嵌来源
+4 -1
View File
@@ -4531,7 +4531,10 @@
"changes/2026-09-15-SITE-07-monaco-basic.md",
"baselines/monaco-core-origins-provenance.json",
"baselines/monaco-core-origins-validation.json",
"changes/2026-09-15-SITE-07-monaco-core-origins.md"
"changes/2026-09-15-SITE-07-monaco-core-origins.md",
"baselines/monaco-core-build-provenance.json",
"baselines/monaco-core-build-validation.json",
"changes/2026-09-15-SITE-07-monaco-core-build.md"
]
},
{
+42
View File
@@ -195,3 +195,45 @@ temporary sanitizer hooks. The site test checks every delivered notice byte and
relative attribution link while exercising mobile playback/logging/disposal.
Neither is an exhaustive sanitizer audit. Loader, other core modules, localization,
and further embedded-origin details remain under SITE-07/VENDOR-06.
## Core minification, loader and locales
`reproduce-core-build.ts` verifies all 13 JavaScript outputs in monaco-editor-core
0.30.1: editor, worker, loader, English and nine translations. The fixed VS Code
recipe and lock identify esbuild 0.12.6. The selected executable is read from a
SHA-512/SHA-256-verified archive and run directly in an ignored cache, without
install scripts or root dependency changes. Windows/Linux x64 archives are pinned;
only Windows execution has been validated. Other hosts fail explicitly.
The historical build's node platform/esnext target/minify options reproduce every
complete output, including the exact extra newline and relative source-map comment.
Twelve files copy directly into the site; editor.main has the previously verified
entry rename and core prefix before appended language registrations. This command
does not claim to reconstruct those registrations or CSS. The loader's full source
and release header match fixed Git; css/nls loader sources match their map entries.
`core-build.ts` contains static NLS parsing, source-map inventory and map-comment
assembly. The NLS parser accepts the archived trailing commas but rejects computed
values, duplicate keys and extra statements without evaluating downloaded code.
Two archived maps contain 584 prepared-source entries, 549 different names, with
content hashes and byte lengths. They are prepared build inputs, not proof of a
complete original VS Code TypeScript compilation or license review.
```sh
yarn verify:monaco-core-build --fetch
yarn verify:monaco-core-build
yarn test:browser test/browser/editor-core.spec.js --workers=1
```
Ten locales each exercise actual keyboard edits, undo/redo, localized find UI,
next-match navigation and model disposal in all engines. The test waits for the
new selected range after changing the query, not a fixed delay or an old cursor
position. A separate diff-editor test requires a real worker, checks changed lines,
updates the input to equality, and disposes both models.
Remaining origin review can start from the map inventory: `dom.ts` references WinJS;
`strings.ts` names unicode-utils generators; `color.ts` references HSL formulas;
marked names a Stack Overflow snippet; `path.ts` identifies Node 14.16.0 while the
older supplied notice links a different commit. Reference comments alone do not
establish copied expression or a missing license; inspect actual boundaries and
original terms before deciding. Core registration assembly and CSS remain separate.
+47
View File
@@ -0,0 +1,47 @@
import assert from 'node:assert/strict'
import path from 'node:path'
import ts from 'typescript'
import { hash } from './archives.ts'
export interface CoreSourceMap { sources: string[], sourcesContent: string[] }
export function inventoryCoreMap(map: CoreSourceMap): { source: string, bytes: number, sha256: string }[] {
assert.equal(map.sources.length, map.sourcesContent.length, 'Missing mapped source content')
assert.equal(new Set(map.sources).size, map.sources.length, 'Repeated mapped source name')
return map.sources.map((source, index) => {
const content = map.sourcesContent[index]
assert(typeof content === 'string', 'Missing mapped source text')
const bytes = new TextEncoder().encode(content)
return { source, bytes: bytes.length, sha256: hash(bytes) }
})
}
export function restoreCoreMapComment(minified: string, relative: string): string {
assert(/^vs\/[\w./-]+\.js$/.test(relative) && !relative.split('/').includes('..'), 'Invalid core output path')
assert(minified.endsWith('\n'), 'Expected esbuild output newline')
const url = path.posix.relative(path.posix.dirname(`min/${relative}`), `min-maps/${relative}.map`)
return `${minified}\n//# sourceMappingURL=${url}`
}
export function readCoreNls(source: string): { id: string, messages: Record<string, string[]> } {
const file = ts.createSourceFile('nls.js', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS)
assert.equal(file.statements.length, 1, 'Expected one NLS registration')
const statement = file.statements[0]!
assert(ts.isExpressionStatement(statement) && ts.isCallExpression(statement.expression), 'Expected literal NLS call')
const call = statement.expression
assert(ts.isIdentifier(call.expression) && call.expression.text === 'define' && call.arguments.length === 2, 'Expected AMD NLS definition')
const name = call.arguments[0]!
assert(ts.isStringLiteral(name), 'Expected NLS module name')
const data = call.arguments[1]!
assert(ts.isObjectLiteralExpression(data), 'Expected literal translation object')
const entries = data.properties.map((property) => {
assert(ts.isPropertyAssignment(property) && ts.isStringLiteral(property.name) && ts.isArrayLiteralExpression(property.initializer), 'Expected literal translation arrays')
return [property.name.text, property.initializer.elements.map((item) => {
assert(ts.isStringLiteral(item), 'Expected literal translation text')
return item.text
})] as const
})
assert.equal(new Set(entries.map(([name]) => name)).size, entries.length, 'Repeated translation module')
const messages = Object.fromEntries(entries)
return { id: name.text, messages }
}
@@ -0,0 +1,92 @@
import type { Archive, Member, Remote } from './archives.ts'
import type { CoreSourceMap } from './core-build.ts'
import assert from 'node:assert/strict'
import { execFileSync } from 'node:child_process'
import fs from 'node:fs'
import path from 'node:path'
import process from 'node:process'
import { fileURLToPath } from 'node:url'
import { ArchiveCache, hash } from './archives.ts'
import { inventoryCoreMap, readCoreNls, restoreCoreMapComment } from './core-build.ts'
interface Record {
commit: string
archives: Archive[]
remotes: Remote[]
binaries: { [platform: string]: Member }
files: { relative: string, development: Member, minified: Member, target: { path: string, sha256: string }, appendedContributions: boolean }[]
sourceMaps: (Member & { sources: ReturnType<typeof inventoryCoreMap> })[]
locales: { path: string, sha256: string }
}
const root = fileURLToPath(new URL('../../../', import.meta.url))
assert(process.argv.slice(2).every(arg => arg === '--fetch'), 'Use reproduce-core-build.ts [--fetch]')
assert.equal(process.version, `v${fs.readFileSync(path.join(root, '.node-version'), 'utf8').trim()}`, 'Use canonical Node')
const record: Record = JSON.parse(fs.readFileSync(path.join(root, 'refactor/baselines/monaco-core-build-provenance.json'), 'utf8'))
const host = `${process.platform}-${process.arch}`
const binary = record.binaries[host]
assert(binary, `No frozen esbuild binary for ${host}`)
const cache = new ArchiveCache(root, path.join(root, 'refactor/.cache/monaco-review'))
const archives = record.archives.filter(item => !item.name.startsWith('esbuild-') || `${item.name}-${item.version}` === binary.archive)
await cache.verify(archives, record.remotes, process.argv.includes('--fetch'))
const lock = fs.readFileSync(path.join(root, 'refactor/baselines/site-vendor/monaco-core-build/build-yarn.lock.txt'), 'utf8')
const esbuild = archives.find(archive => archive.name === 'esbuild')
assert(esbuild && lock.includes(`esbuild@^0.12.6:\n version "0.12.6"`) && lock.includes(`integrity ${esbuild.integrity}`), 'Wrong historical minifier')
const executable = path.join(cache.directory, process.platform === 'win32' ? 'core-esbuild.exe' : 'core-esbuild')
assert(!fs.existsSync(executable) || !fs.lstatSync(executable).isSymbolicLink(), 'Redirected historical executable')
fs.writeFileSync(executable, cache.member(binary), { mode: 0o700 })
assert.equal(execFileSync(executable, ['--version'], { encoding: 'utf8' }).trim(), '0.12.6')
const sourceFile = path.join(cache.directory, 'core-reproduction-input.js')
assert(!fs.existsSync(sourceFile) || !fs.lstatSync(sourceFile).isSymbolicLink(), 'Redirected historical input')
const archiveFiles = execFileSync('tar', ['-tzf', path.join(cache.directory, 'monaco-editor-core-0.30.1.tgz')], { encoding: 'utf8' }).trim().split(/\r?\n/)
assert.deepEqual(record.files.map(file => file.development.member).sort(), archiveFiles.filter(file => file.startsWith('package/dev/') && file.endsWith('.js')).sort(), 'Missing core JavaScript output')
assert.equal(record.files.length, 13)
const results = []
for (const file of record.files) {
const development = cache.member(file.development)
fs.writeFileSync(sourceFile, development)
const output = execFileSync(executable, [sourceFile, '--minify', '--platform=node', '--target=esnext'], { encoding: 'utf8', maxBuffer: 30 * 1024 * 1024 })
const minified = cache.member(file.minified).toString('utf8')
assert.equal(restoreCoreMapComment(output, file.relative), minified, 'Core minification differs')
const shipped = fs.readFileSync(path.join(root, file.target.path))
assert.equal(hash(shipped), file.target.sha256, 'Core site asset changed')
assert.deepEqual(shipped, cache.read('monaco-editor-0.30.1', `package/min/${file.relative}`), 'Core editor archive differs')
if (file.appendedContributions) {
assert.equal(file.relative, 'vs/editor/editor.main.js')
const renamed = minified.replace('"vs/editor/editor.main"', '"vs/editor/edcore.main"')
const offset = renamed.lastIndexOf('//# sourceMappingURL=')
assert(shipped.toString('utf8').startsWith(renamed.slice(0, offset)) && shipped.toString('utf8').endsWith(renamed.slice(offset)), 'Editor core boundary differs')
}
else {
assert.equal(shipped.toString('utf8'), minified, 'Core copied output differs')
}
results.push({ relative: file.relative, exactMinification: true, appendedContributions: file.appendedContributions, sha256: hash(shipped) })
}
const maps: CoreSourceMap[] = []
for (const member of record.sourceMaps) {
const map: CoreSourceMap = JSON.parse(cache.member(member).toString('utf8'))
assert.deepEqual(inventoryCoreMap(map), member.sources, 'Prepared source inventory differs')
maps.push(map)
}
for (const name of ['loader', 'css', 'nls']) {
const remote = record.remotes.find(remote => remote.source.endsWith(`src-vs-${name}.js.txt`))
assert(remote)
const source = fs.readFileSync(path.join(root, remote.source), 'utf8')
const map = maps.find(map => map.sources.includes(`vs/${name}.js`))
assert(map)
assert.equal(map.sourcesContent[map.sources.indexOf(`vs/${name}.js`)], source, 'Loader source differs')
if (name === 'loader') {
const header = `/*!-----------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Version: 0.30.1(${record.commit})\n * Released under the MIT license\n * https://github.com/microsoft/vscode/blob/main/LICENSE.txt\n *-----------------------------------------------------------*/\n\n`
assert.equal(cache.read('monaco-editor-core-0.30.1', 'package/dev/vs/loader.js').toString('utf8'), header + source, 'Loader release header differs')
}
}
const locales = fs.readFileSync(path.join(root, record.locales.path))
assert.equal(hash(locales), record.locales.sha256)
for (const locale of JSON.parse(locales.toString('utf8'))) {
assert(record.files.some(file => file.development.member === locale.member), 'Unverified locale')
const { id, messages } = readCoreNls(cache.read('monaco-editor-core-0.30.1', locale.member).toString('utf8'))
assert.equal(id, `vs/editor/editor.main.nls${locale.locale === 'en' ? '' : `.${locale.locale}`}`)
const labels = messages['vs/editor/contrib/find/findWidget']!
assert.deepEqual([locale.find, locale.next, locale.close], [labels[7], labels[10], labels[12]], 'Locale fixture differs')
}
console.log(JSON.stringify({ host, archives: archives.length, gitSources: record.remotes.length, outputs: results, mappedInstances: maps.reduce((count, map) => count + map.sources.length, 0), uniqueMappedSources: new Set(maps.flatMap(map => map.sources)).size, completeTypeScriptBuild: false, remainingEmbeddedOriginsReviewed: false }))
+6
View File
@@ -1,5 +1,11 @@
# Browser regression entry
`editor-core.spec.js` checks editing, keyboard undo/redo, find navigation and disposal
for all ten bundled locales. Names come from statically parsed frozen NLS inputs;
each localized bundle must load over HTTP. A separate case requires the real core
diff worker to compute and clear changes after input updates. On Windows the ten
locale cases and worker case pass in Chromium/Firefox/WebKit (33 cases total).
`editor-markdown.spec.js` runs the bundled DOMPurify/marked renderer, verifies
formatting, selected filtering and temporary-hook cleanup. `site-vendor.spec.js`
also checks all 85 notice files and the core-origin attribution links over HTTP.
+105
View File
@@ -0,0 +1,105 @@
import fs from 'node:fs'
import { expect, test } from './fixtures.js'
const locales = JSON.parse(fs.readFileSync(new URL('../../refactor/baselines/monaco-core-locales.json', import.meta.url)))
test('docs Monaco core diff worker computes changes and updates after edits', async ({ page }, testInfo) => {
const workers = []
page.on('worker', worker => workers.push(worker.url()))
await page.goto('/test/player.html?core=candidate&chapter=published')
await page.addScriptTag({ url: '/assets/js/vs/loader.js' })
await page.evaluate(async () => {
window.require.config({ paths: { vs: '/assets/js/vs' } })
await new Promise((resolve, reject) => window.require(['vs/editor/editor.main'], resolve, reject))
const host = document.createElement('div')
host.style.cssText = 'width:800px;height:400px'
document.body.appendChild(host)
const api = window.monaco.editor
const original = api.createModel('first\nsecond\nthird', 'plaintext')
const modified = api.createModel('first\nchanged\nthird', 'plaintext')
const editor = api.createDiffEditor(host)
editor.setModel({ original, modified })
window.diffProbe = { host, editor, original, modified }
})
try {
await expect.poll(() => page.evaluate(() => window.diffProbe.editor.getLineChanges()?.map(change => [change.originalStartLineNumber, change.originalEndLineNumber, change.modifiedStartLineNumber, change.modifiedEndLineNumber]))).toEqual([[2, 2, 2, 2]])
expect(workers.length).toBeGreaterThan(0)
await page.evaluate(() => window.diffProbe.modified.setValue(window.diffProbe.original.getValue()))
await expect.poll(() => page.evaluate(() => window.diffProbe.editor.getLineChanges())).toEqual([])
await testInfo.attach('monaco-core-worker', { contentType: 'application/json', body: JSON.stringify({ workers, initialChangedLines: [2, 2, 2, 2], finalChanges: [] }) })
}
finally {
await page.evaluate(() => {
const { host, editor, original, modified } = window.diffProbe
editor.dispose()
original.dispose()
modified.dispose()
host.remove()
})
}
expect(await page.evaluate(() => window.monaco.editor.getModels().length)).toBe(0)
})
for (const locale of locales) {
test(`docs Monaco core editing and localized find: ${locale.locale}`, async ({ page }, testInfo) => {
const responses = []
page.on('response', (response) => {
if (/editor\.main\.nls/.test(response.url()))
responses.push({ url: response.url(), status: response.status() })
})
await page.goto('/test/player.html?core=candidate&chapter=published')
await page.addScriptTag({ url: '/assets/js/vs/loader.js' })
const modifier = await page.evaluate(async (locale) => {
window.require.config({ 'paths': { vs: '/assets/js/vs' }, 'vs/nls': { availableLanguages: locale === 'en' ? {} : { '*': locale } } })
const load = ids => new Promise((resolve, reject) => window.require(ids, (...modules) => resolve(modules), reject))
await load(['vs/editor/editor.main'])
const [platform] = await load(['vs/base/common/platform'])
const host = document.createElement('div')
host.style.cssText = 'width:800px;height:400px'
document.body.appendChild(host)
const editor = window.monaco.editor.create(host, { value: 'first\nsecond\nfirst', language: 'plaintext', minimap: { enabled: false } })
editor.setPosition({ lineNumber: 1, column: 6 })
editor.focus()
window.coreProbe = { editor, host }
return platform.isMacintosh ? 'Meta' : 'Control'
}, locale.locale)
try {
await page.keyboard.insertText(' beta')
await expect.poll(() => page.evaluate(() => window.coreProbe.editor.getValue())).toBe('first beta\nsecond\nfirst')
await page.keyboard.press(`${modifier}+z`)
await expect.poll(() => page.evaluate(() => window.coreProbe.editor.getValue())).toBe('first\nsecond\nfirst')
await page.keyboard.press(modifier === 'Meta' ? 'Meta+Shift+z' : 'Control+y')
await expect.poll(() => page.evaluate(() => window.coreProbe.editor.getValue())).toBe('first beta\nsecond\nfirst')
await page.evaluate(() => {
window.coreProbe.editor.setPosition({ lineNumber: 1, column: 1 })
return window.coreProbe.editor.getAction('actions.find').run()
})
const input = page.getByRole('textbox', { name: locale.find, exact: true })
await expect(input).toBeVisible()
await expect(input).toHaveAttribute('aria-label', locale.find)
await input.fill('st')
await expect.poll(() => page.evaluate(() => {
const selection = window.coreProbe.editor.getSelection()
return [selection.startLineNumber, selection.startColumn, selection.endColumn]
})).toEqual([1, 4, 6])
await input.press('Enter')
await expect.poll(() => page.evaluate(() => window.coreProbe.editor.getSelection().startLineNumber)).toBe(3)
await input.press('Escape')
await expect(input).not.toBeVisible()
expect(responses).toHaveLength(1)
expect(responses[0].status).toBe(200)
expect(responses[0].url).toContain(`editor.main.nls${locale.locale === 'en' ? '' : `.${locale.locale}`}.js`)
await testInfo.attach('monaco-core-editing', { contentType: 'application/json', body: JSON.stringify({ locale, modifier, responses }) })
}
finally {
await page.evaluate(() => {
const { editor, host } = window.coreProbe
const model = editor.getModel()
editor.dispose()
model.dispose()
host.remove()
})
}
expect(await page.evaluate(() => window.monaco.editor.getModels().length)).toBe(0)
})
}
+17
View File
@@ -4,10 +4,27 @@ import test from 'node:test'
import ts from 'typescript'
import { extractBasicFixtures } from '../scripts/site-vendor/monaco/basic-fixtures.ts'
import { emitAmd } from '../scripts/site-vendor/monaco/compiler.ts'
import { inventoryCoreMap, readCoreNls, restoreCoreMapComment } from '../scripts/site-vendor/monaco/core-build.ts'
import { adaptCoreOrigin } from '../scripts/site-vendor/monaco/core-origins.ts'
import { aliasModule, moduleIds, nameModule, verifyWorkerSources } from '../scripts/site-vendor/monaco/languages.ts'
import { browserTypeScript, verifyTypeScriptSource } from '../scripts/site-vendor/monaco/typescript.ts'
test('Core NLS extraction accepts historical trailing commas without evaluating expressions', () => {
assert.deepEqual(readCoreNls('define("nls", { "find": ["Find", "查找",], });'), { id: 'nls', messages: { find: ['Find', '查找'] } })
assert.throws(() => readCoreNls('define("nls", { "find": [translate()], });'), /literal translation text/)
assert.throws(() => readCoreNls('define("nls", { "find": [], "find": [] });'), /Repeated translation/)
assert.throws(() => readCoreNls('run(); define("nls", {});'), /one NLS registration/)
})
test('Core source inventories and map comments reject incomplete or ambiguous evidence', () => {
assert.equal(inventoryCoreMap({ sources: ['test'], sourcesContent: ['查找'] })[0].bytes, 6)
assert.throws(() => inventoryCoreMap({ sources: ['a'], sourcesContent: [] }), /Missing mapped/)
assert.throws(() => inventoryCoreMap({ sources: ['a', 'a'], sourcesContent: ['', ''] }), /Repeated mapped/)
assert.equal(restoreCoreMapComment('code;\n', 'vs/loader.js'), 'code;\n\n//# sourceMappingURL=../../min-maps/vs/loader.js.map')
assert.throws(() => restoreCoreMapComment('code;', 'vs/loader.js'), /newline/)
assert.throws(() => restoreCoreMapComment('code;\n', 'vs/../outside.js'), /output path/)
})
test('Core origin adaptation rejects duplicate boundaries and preserves replacement bytes', () => {
const edits = [{ before: 'export default purify;', after: 'define(factory); // $&' }]
assert.equal(adaptCoreOrigin('export default purify;', edits), 'define(factory); // $&')