importEditorWebpackPlugin.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See LICENSE in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. //@ts-check
  6. const glob = require('glob');
  7. const path = require('path');
  8. const fs = require('fs');
  9. const { REPO_ROOT } = require('./utils');
  10. const customFeatureLabels = {
  11. 'vs/editor/browser/controller/coreCommands': 'coreCommands',
  12. 'vs/editor/contrib/caretOperations/caretOperations': 'caretOperations',
  13. 'vs/editor/contrib/caretOperations/transpose': 'transpose',
  14. 'vs/editor/contrib/colorPicker/colorDetector': 'colorDetector',
  15. 'vs/editor/contrib/rename/onTypeRename': 'onTypeRename',
  16. 'vs/editor/contrib/gotoSymbol/link/goToDefinitionAtPosition': 'gotoSymbol',
  17. 'vs/editor/contrib/snippet/snippetController2': 'snippets',
  18. 'vs/editor/standalone/browser/quickAccess/standaloneGotoLineQuickAccess': 'gotoLine',
  19. 'vs/editor/standalone/browser/quickAccess/standaloneCommandsQuickAccess': 'quickCommand',
  20. 'vs/editor/standalone/browser/quickAccess/standaloneGotoSymbolQuickAccess': 'quickOutline',
  21. 'vs/editor/standalone/browser/quickAccess/standaloneHelpQuickAccess': 'quickHelp'
  22. };
  23. generateLanguages();
  24. generateFeatures();
  25. /**
  26. * @returns { Promise<{ label: string; entry: string; }[]> }
  27. */
  28. function getBasicLanguages() {
  29. return new Promise((resolve, reject) => {
  30. glob(
  31. './release/esm/vs/basic-languages/*/*.contribution.js',
  32. { cwd: path.dirname(__dirname) },
  33. (err, files) => {
  34. if (err) {
  35. reject(err);
  36. return;
  37. }
  38. resolve(
  39. files.map((file) => {
  40. const entry = file.substring('./release/esm/'.length).replace(/\.js$/, '');
  41. const label = path.basename(file).replace(/\.contribution\.js$/, '');
  42. return {
  43. label: label,
  44. entry: entry
  45. };
  46. })
  47. );
  48. }
  49. );
  50. });
  51. }
  52. /**
  53. * @returns { Promise<string[]> }
  54. */
  55. function readAdvancedLanguages() {
  56. return new Promise((resolve, reject) => {
  57. glob(
  58. './release/esm/vs/language/*/monaco.contribution.js',
  59. { cwd: path.dirname(__dirname) },
  60. (err, files) => {
  61. if (err) {
  62. reject(err);
  63. return;
  64. }
  65. resolve(
  66. files
  67. .map((file) => file.substring('./release/esm/vs/language/'.length))
  68. .map((file) => file.substring(0, file.length - '/monaco.contribution.js'.length))
  69. );
  70. }
  71. );
  72. });
  73. }
  74. /**
  75. * @returns { Promise<{ label: string; entry: string; worker: { id: string; entry: string; }; }[]> }
  76. */
  77. function getAdvancedLanguages() {
  78. return readAdvancedLanguages().then((languages) => {
  79. let result = [];
  80. for (const lang of languages) {
  81. let shortLang = lang === 'typescript' ? 'ts' : lang;
  82. const entry = `vs/language/${lang}/monaco.contribution`;
  83. checkFileExists(entry);
  84. const workerId = `vs/language/${lang}/${shortLang}Worker`;
  85. const workerEntry = `vs/language/${lang}/${shortLang}.worker`;
  86. checkFileExists(workerEntry);
  87. result.push({
  88. label: lang,
  89. entry: entry,
  90. worker: {
  91. id: workerId,
  92. entry: workerEntry
  93. }
  94. });
  95. }
  96. return result;
  97. });
  98. function checkFileExists(moduleName) {
  99. const filePath = path.join(REPO_ROOT, 'release/esm', `${moduleName}.js`);
  100. if (!fs.existsSync(filePath)) {
  101. console.error(`Could not find ${filePath}.`);
  102. process.exit(1);
  103. }
  104. }
  105. }
  106. function generateLanguages() {
  107. return Promise.all([getBasicLanguages(), getAdvancedLanguages()]).then(
  108. ([basicLanguages, advancedLanguages]) => {
  109. basicLanguages.sort(strcmp);
  110. advancedLanguages.sort(strcmp);
  111. let i = 0,
  112. len = basicLanguages.length;
  113. let j = 0,
  114. lenJ = advancedLanguages.length;
  115. let result = [];
  116. while (i < len || j < lenJ) {
  117. if (i < len && j < lenJ) {
  118. if (basicLanguages[i].label === advancedLanguages[j].label) {
  119. let entry = [];
  120. entry.push(basicLanguages[i].entry);
  121. entry.push(advancedLanguages[j].entry);
  122. result.push({
  123. label: basicLanguages[i].label,
  124. entry: entry,
  125. worker: advancedLanguages[j].worker
  126. });
  127. i++;
  128. j++;
  129. } else if (basicLanguages[i].label < advancedLanguages[j].label) {
  130. result.push(basicLanguages[i]);
  131. i++;
  132. } else {
  133. result.push(advancedLanguages[j]);
  134. j++;
  135. }
  136. } else if (i < len) {
  137. result.push(basicLanguages[i]);
  138. i++;
  139. } else {
  140. result.push(advancedLanguages[j]);
  141. j++;
  142. }
  143. }
  144. const code = `//
  145. // THIS IS A GENERATED FILE. PLEASE DO NOT EDIT DIRECTLY.
  146. // GENERATED USING node scripts/import-editor.js
  147. //
  148. import { IFeatureDefinition } from "./types";
  149. export const languagesArr: IFeatureDefinition[] = ${JSON.stringify(result, null, ' ')
  150. .replace(/"label":/g, 'label:')
  151. .replace(/"entry":/g, 'entry:')
  152. .replace(/"worker":/g, 'worker:')
  153. .replace(/"id":/g, 'id:')
  154. .replace(/"/g, "'")};
  155. export type EditorLanguage = ${result.map((el) => `'${el.label}'`).join(' | ')};
  156. `;
  157. fs.writeFileSync(
  158. path.join(REPO_ROOT, 'webpack-plugin/src/languages.ts'),
  159. code.replace(/\r\n/g, '\n')
  160. );
  161. const readmeLanguages = JSON.stringify(result.map((r) => r.label))
  162. .replace(/"/g, "'")
  163. .replace(/','/g, "', '");
  164. let readme = fs.readFileSync(path.join(REPO_ROOT, 'webpack-plugin/README.md')).toString();
  165. readme = readme.replace(
  166. /<!-- LANGUAGES_BEGIN -->([^<]+)<!-- LANGUAGES_END -->/,
  167. `<!-- LANGUAGES_BEGIN -->\`${readmeLanguages}\`<!-- LANGUAGES_END -->`
  168. );
  169. fs.writeFileSync(path.join(REPO_ROOT, 'webpack-plugin/README.md'), readme);
  170. }
  171. );
  172. }
  173. /**
  174. * @tyoe {string} a
  175. * @tyoe {string} b
  176. */
  177. function strcmp(a, b) {
  178. if (a < b) {
  179. return -1;
  180. }
  181. if (a > b) {
  182. return 1;
  183. }
  184. return 0;
  185. }
  186. function generateFeatures() {
  187. const skipImports = [
  188. 'vs/editor/browser/widget/codeEditorWidget',
  189. 'vs/editor/browser/widget/diffEditorWidget',
  190. 'vs/editor/browser/widget/diffNavigator',
  191. 'vs/editor/common/standaloneStrings',
  192. 'vs/editor/contrib/tokenization/tokenization',
  193. 'vs/editor/editor.all',
  194. 'vs/base/browser/ui/codicons/codiconStyles',
  195. 'vs/editor/contrib/gotoSymbol/documentSymbols'
  196. ];
  197. /** @type {string[]} */
  198. let features = [];
  199. const files =
  200. fs.readFileSync(path.join(REPO_ROOT, 'release/esm/vs/editor/edcore.main.js')).toString() +
  201. fs.readFileSync(path.join(REPO_ROOT, 'release/esm/vs/editor/editor.all.js')).toString();
  202. files.split(/\r\n|\n/).forEach((line) => {
  203. const m = line.match(/import '([^']+)'/);
  204. if (m) {
  205. const tmp = path.posix.join('vs/editor', m[1]).replace(/\.js$/, '');
  206. if (skipImports.indexOf(tmp) === -1) {
  207. features.push(tmp);
  208. }
  209. }
  210. });
  211. /** @type {{label:string;entry:any;}[]} */
  212. let result = features.map((feature) => {
  213. return {
  214. label: customFeatureLabels[feature] || path.basename(path.dirname(feature)),
  215. entry: feature
  216. };
  217. });
  218. result.sort((a, b) => {
  219. const labelCmp = strcmp(a.label, b.label);
  220. if (labelCmp === 0) {
  221. return strcmp(a.entry, b.entry);
  222. }
  223. return labelCmp;
  224. });
  225. for (let i = 0; i < result.length; i++) {
  226. if (i + 1 < result.length && result[i].label === result[i + 1].label) {
  227. if (typeof result[i].entry === 'string') {
  228. result[i].entry = [result[i].entry];
  229. }
  230. result[i].entry.push(result[i + 1].entry);
  231. result.splice(i + 1, 1);
  232. }
  233. }
  234. const code = `//
  235. // THIS IS A GENERATED FILE. PLEASE DO NOT EDIT DIRECTLY.
  236. // GENERATED USING node scripts/import-editor.js
  237. //
  238. import { IFeatureDefinition } from "./types";
  239. export const featuresArr: IFeatureDefinition[] = ${JSON.stringify(result, null, ' ')
  240. .replace(/"label":/g, 'label:')
  241. .replace(/"entry":/g, 'entry:')
  242. .replace(/"/g, "'")};
  243. export type EditorFeature = ${result.map((el) => `'${el.label}'`).join(' | ')};
  244. export type NegatedEditorFeature = ${result.map((el) => `'!${el.label}'`).join(' | ')};
  245. `;
  246. fs.writeFileSync(
  247. path.join(REPO_ROOT, 'webpack-plugin/src/features.ts'),
  248. code.replace(/\r\n/g, '\n')
  249. );
  250. const readmeFeatures = JSON.stringify(result.map((r) => r.label))
  251. .replace(/"/g, "'")
  252. .replace(/','/g, "', '");
  253. let readme = fs.readFileSync(path.join(REPO_ROOT, 'webpack-plugin/README.md')).toString();
  254. readme = readme.replace(
  255. /<!-- FEATURES_BEGIN -->([^<]+)<!-- FEATURES_END -->/,
  256. `<!-- FEATURES_BEGIN -->\`${readmeFeatures}\`<!-- FEATURES_END -->`
  257. );
  258. fs.writeFileSync(path.join(REPO_ROOT, 'webpack-plugin/README.md'), readme);
  259. }