monaco-editor/build/importEditorWebpackPlugin.js

292 lines
8.3 KiB
JavaScript

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