import-editor.js 8.2 KB

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