gulpfile.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. var gulp = require('gulp');
  2. var metadata = require('./metadata');
  3. var es = require('event-stream');
  4. var path = require('path');
  5. var fs = require('fs');
  6. var rimraf = require('rimraf');
  7. var cp = require('child_process');
  8. var httpServer = require('http-server');
  9. var typedoc = require("gulp-typedoc");
  10. var WEBSITE_GENERATED_PATH = path.join(__dirname, 'website/playground/new-samples');
  11. var MONACO_EDITOR_VERSION = (function() {
  12. var packageJsonPath = path.join(__dirname, 'package.json');
  13. var packageJson = JSON.parse(fs.readFileSync(packageJsonPath).toString());
  14. var version = packageJson.version;
  15. if (!/\d+\.\d+\.\d+/.test(version)) {
  16. console.log('unrecognized package.json version: ' + version);
  17. process.exit(0);
  18. }
  19. return version;
  20. })();
  21. gulp.task('clean-release', function(cb) { rimraf('release', { maxBusyTries: 1 }, cb); });
  22. gulp.task('release', ['clean-release'], function() {
  23. return es.merge(
  24. // dev folder
  25. releaseOne('dev'),
  26. // min folder
  27. releaseOne('min'),
  28. // package.json
  29. gulp.src('package.json')
  30. .pipe(es.through(function(data) {
  31. var json = JSON.parse(data.contents.toString());
  32. json.private = false;
  33. data.contents = new Buffer(JSON.stringify(json, null, ' '));
  34. this.emit('data', data);
  35. }))
  36. .pipe(gulp.dest('release')),
  37. gulp.src('CHANGELOG.md'),
  38. // min-maps folder
  39. gulp.src('node_modules/monaco-editor-core/min-maps/**/*').pipe(gulp.dest('release/min-maps')),
  40. // other files
  41. gulp.src([
  42. 'node_modules/monaco-editor-core/LICENSE',
  43. 'node_modules/monaco-editor-core/monaco.d.ts',
  44. 'node_modules/monaco-editor-core/ThirdPartyNotices.txt',
  45. 'README.md'
  46. ])
  47. .pipe(addPluginDTS())
  48. .pipe(addPluginThirdPartyNotices())
  49. .pipe(gulp.dest('release'))
  50. )
  51. });
  52. function releaseOne(type) {
  53. return es.merge(
  54. gulp.src('node_modules/monaco-editor-core/' + type + '/**/*')
  55. .pipe(addPluginContribs())
  56. .pipe(gulp.dest('release/' + type)),
  57. pluginStreams('release/' + type + '/')
  58. )
  59. }
  60. function pluginStreams(destinationPath) {
  61. return es.merge(
  62. metadata.METADATA.PLUGINS.map(function(plugin) {
  63. return pluginStream(plugin, destinationPath);
  64. })
  65. );
  66. }
  67. function pluginStream(plugin, destinationPath) {
  68. var contribPath = path.join(plugin.paths.npm, plugin.contrib.substr(plugin.modulePrefix.length)) + '.js';
  69. return (
  70. gulp.src([
  71. plugin.paths.npm + '/**/*',
  72. '!' + contribPath,
  73. '!' + plugin.paths.npm + '/**/monaco.d.ts'
  74. ])
  75. .pipe(gulp.dest(destinationPath + plugin.modulePrefix))
  76. );
  77. }
  78. /**
  79. * Edit editor.main.js:
  80. * - rename the AMD module 'vs/editor/editor.main' to 'vs/editor/edcore.main'
  81. * - append contribs from plugins
  82. * - append new AMD module 'vs/editor/editor.main' that stiches things together
  83. */
  84. function addPluginContribs() {
  85. return es.through(function(data) {
  86. if (!/editor\.main\.js$/.test(data.path)) {
  87. this.emit('data', data);
  88. return;
  89. }
  90. var contents = data.contents.toString();
  91. // Rename the AMD module 'vs/editor/editor.main' to 'vs/editor/edcore.main'
  92. contents = contents.replace(/"vs\/editor\/editor\.main\"/, '"vs/editor/edcore.main"');
  93. var extraContent = [];
  94. var allPluginsModuleIds = [];
  95. metadata.METADATA.PLUGINS.forEach(function(plugin) {
  96. allPluginsModuleIds.push(plugin.contrib);
  97. var contribPath = path.join(__dirname, plugin.paths.npm, plugin.contrib.substr(plugin.modulePrefix.length)) + '.js';
  98. var contribContents = fs.readFileSync(contribPath).toString();
  99. var contribDefineIndex = contribContents.indexOf('define("' + plugin.contrib);
  100. if (contribDefineIndex === -1) {
  101. console.error('(1) CANNOT DETERMINE AMD define location for contribution', plugin);
  102. process.exit(-1);
  103. }
  104. var depsEndIndex = contribContents.indexOf(']', contribDefineIndex);
  105. if (contribDefineIndex === -1) {
  106. console.error('(2) CANNOT DETERMINE AMD define location for contribution', plugin);
  107. process.exit(-1);
  108. }
  109. contribContents = contribContents.substring(0, depsEndIndex) + ',"vs/editor/edcore.main"' + contribContents.substring(depsEndIndex);
  110. extraContent.push(contribContents);
  111. });
  112. extraContent.push(`define("vs/editor/editor.main", ["vs/editor/edcore.main","${allPluginsModuleIds.join('","')}"], function() {});`);
  113. var insertIndex = contents.lastIndexOf('//# sourceMappingURL=');
  114. if (insertIndex === -1) {
  115. insertIndex = contents.length;
  116. }
  117. contents = contents.substring(0, insertIndex) + '\n' + extraContent.join('\n') + '\n' + contents.substring(insertIndex);
  118. data.contents = new Buffer(contents);
  119. this.emit('data', data);
  120. });
  121. }
  122. /**
  123. * Edit monaco.d.ts:
  124. * - append monaco.d.ts from plugins
  125. */
  126. function addPluginDTS() {
  127. return es.through(function(data) {
  128. if (!/monaco\.d\.ts$/.test(data.path)) {
  129. this.emit('data', data);
  130. return;
  131. }
  132. var contents = data.contents.toString();
  133. var extraContent = [];
  134. metadata.METADATA.PLUGINS.forEach(function(plugin) {
  135. var dtsPath = path.join(plugin.paths.npm, 'monaco.d.ts');
  136. try {
  137. extraContent.push(fs.readFileSync(dtsPath).toString());
  138. } catch (err) {
  139. return;
  140. }
  141. });
  142. contents = [
  143. '/*!-----------------------------------------------------------',
  144. ' * Copyright (c) Microsoft Corporation. All rights reserved.',
  145. ' * Type definitions for monaco-editor v'+MONACO_EDITOR_VERSION,
  146. ' * Released under the MIT license',
  147. '*-----------------------------------------------------------*/',
  148. ].join('\n') + '\n' + contents + '\n' + extraContent.join('\n');
  149. // Ensure consistent indentation and line endings
  150. contents = cleanFile(contents);
  151. data.contents = new Buffer(contents);
  152. fs.writeFileSync('website/playground/monaco.d.ts.txt', contents);
  153. fs.writeFileSync('monaco.d.ts', contents);
  154. this.emit('data', data);
  155. });
  156. }
  157. /**
  158. * Normalize line endings and ensure consistent 4 spaces indentation
  159. */
  160. function cleanFile(contents) {
  161. return contents.split(/\r\n|\r|\n/).map(function(line) {
  162. var m = line.match(/^(\t+)/);
  163. if (!m) {
  164. return line;
  165. }
  166. var tabsCount = m[1].length;
  167. var newIndent = '';
  168. for (var i = 0; i < 4 * tabsCount; i++) {
  169. newIndent += ' ';
  170. }
  171. return newIndent + line.substring(tabsCount);
  172. }).join('\n');
  173. }
  174. /**
  175. * Edit ThirdPartyNotices.txt:
  176. * - append ThirdPartyNotices.txt from plugins
  177. */
  178. function addPluginThirdPartyNotices() {
  179. return es.through(function(data) {
  180. if (!/ThirdPartyNotices\.txt$/.test(data.path)) {
  181. this.emit('data', data);
  182. return;
  183. }
  184. var contents = data.contents.toString();
  185. var extraContent = [];
  186. metadata.METADATA.PLUGINS.forEach(function(plugin) {
  187. var thirdPartyNoticePath = path.join(path.dirname(plugin.paths.npm), 'ThirdPartyNotices.txt');
  188. try {
  189. var thirdPartyNoticeContent = fs.readFileSync(thirdPartyNoticePath).toString();
  190. thirdPartyNoticeContent = thirdPartyNoticeContent.split('\n').slice(8).join('\n');
  191. extraContent.push(thirdPartyNoticeContent);
  192. } catch (err) {
  193. return;
  194. }
  195. });
  196. contents += '\n' + extraContent.join('\n');
  197. data.contents = new Buffer(contents);
  198. this.emit('data', data);
  199. });
  200. }
  201. // --- website
  202. gulp.task('clean-website', function(cb) { rimraf('../monaco-editor-website', { maxBusyTries: 1 }, cb); });
  203. gulp.task('website', ['clean-website'], function() {
  204. return (
  205. es.merge(
  206. gulp.src([
  207. 'website/**/*',
  208. '!website/typedoc-theme/**'
  209. ], { dot: true })
  210. .pipe(es.through(function(data) {
  211. if (!data.contents || !/\.(html)$/.test(data.path)) {
  212. return this.emit('data', data);
  213. }
  214. var contents = data.contents.toString();
  215. contents = contents.replace(/\.\.\/release\/dev/g, 'node_modules/monaco-editor/min');
  216. contents = contents.replace(/{{version}}/g, MONACO_EDITOR_VERSION);
  217. // contents = contents.replace('&copy; 2016 Microsoft', '&copy; 2016 Microsoft [' + builtTime + ']');
  218. data.contents = new Buffer(contents);
  219. this.emit('data', data);
  220. }))
  221. .pipe(gulp.dest('../monaco-editor-website')),
  222. // node_modules\.bin\typedoc --mode file --out out src\monaco.d.ts --includeDeclarations --theme default --entryPoint monaco --name "Monaco Editor v0.7.0 API" --readme none --hideGenerator
  223. gulp.src('monaco.d.ts')
  224. .pipe(typedoc({
  225. mode: 'file',
  226. out: '../monaco-editor-website/api',
  227. includeDeclarations: true,
  228. theme: 'website/typedoc-theme',
  229. entryPoint: 'monaco',
  230. name: 'Monaco Editor API v' + MONACO_EDITOR_VERSION,
  231. readme: 'none',
  232. hideGenerator: true
  233. }))
  234. )
  235. .pipe(es.through(function(data) {
  236. this.emit('data', data);
  237. }, function() {
  238. // temporarily create package.json so that npm install doesn't bark
  239. fs.writeFileSync('../monaco-editor-website/package.json', '{}');
  240. cp.execSync('npm install monaco-editor', {
  241. cwd: path.join(__dirname, '../monaco-editor-website')
  242. });
  243. fs.unlink('../monaco-editor-website/package.json');
  244. cp.execSync('git init', {
  245. cwd: path.join(__dirname, '../monaco-editor-website')
  246. });
  247. cp.execSync('git checkout -b gh-pages', {
  248. cwd: path.join(__dirname, '../monaco-editor-website')
  249. });
  250. cp.execSync('git add .', {
  251. cwd: path.join(__dirname, '../monaco-editor-website')
  252. });
  253. cp.execSync('git commit -m "Publish website"', {
  254. cwd: path.join(__dirname, '../monaco-editor-website')
  255. });
  256. cp.execSync('git remote add origin https://github.com/Microsoft/monaco-editor.git', {
  257. cwd: path.join(__dirname, '../monaco-editor-website')
  258. });
  259. console.log('RUN monaco-editor-website>git push origin gh-pages --force')
  260. this.emit('end');
  261. }))
  262. );
  263. });
  264. gulp.task('generate-test-samples', function() {
  265. var sampleNames = fs.readdirSync(path.join(__dirname, 'test/samples'));
  266. var samples = sampleNames.map(function(sampleName) {
  267. var samplePath = path.join(__dirname, 'test/samples', sampleName);
  268. var sampleContent = fs.readFileSync(samplePath).toString();
  269. return {
  270. name: sampleName,
  271. content: sampleContent
  272. };
  273. });
  274. var prefix = '//This is a generated file via gulp generate-test-samples\ndefine([], function() { return';
  275. var suffix = '; });'
  276. fs.writeFileSync(path.join(__dirname, 'test/samples-all.generated.js'), prefix + JSON.stringify(samples, null, '\t') + suffix );
  277. var PLAY_SAMPLES = require(path.join(WEBSITE_GENERATED_PATH, 'all.js')).PLAY_SAMPLES;
  278. var locations = [];
  279. for (var i = 0; i < PLAY_SAMPLES.length; i++) {
  280. var sample = PLAY_SAMPLES[i];
  281. var sampleId = sample.id;
  282. var samplePath = path.join(WEBSITE_GENERATED_PATH, sample.path);
  283. var html = fs.readFileSync(path.join(samplePath, 'sample.html'));
  284. var js = fs.readFileSync(path.join(samplePath, 'sample.js'));
  285. var css = fs.readFileSync(path.join(samplePath, 'sample.css'));
  286. var result = [
  287. '<!DOCTYPE html>',
  288. '<!-- THIS IS A GENERATED FILE VIA gulp generate-test-samples -->',
  289. '<html>',
  290. '<head>',
  291. ' <base href="..">',
  292. ' <meta http-equiv="X-UA-Compatible" content="IE=edge" />',
  293. ' <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />',
  294. '</head>',
  295. '<body>',
  296. '<style>',
  297. '/*----------------------------------------SAMPLE CSS START*/',
  298. '',
  299. css,
  300. '',
  301. '/*----------------------------------------SAMPLE CSS END*/',
  302. '</style>',
  303. '<a class="loading-opts" href="playground.generated/index.html">[&lt;&lt; BACK]</a> <br/>',
  304. 'THIS IS A GENERATED FILE VIA gulp generate-test-samples',
  305. '',
  306. '<div id="bar" style="margin-bottom: 6px;"></div>',
  307. '',
  308. '<div style="clear:both"></div>',
  309. '<div id="outer-container" style="width:800px;height:450px;border: 1px solid grey">',
  310. '<!-- ----------------------------------------SAMPLE HTML START-->',
  311. '',
  312. html,
  313. '',
  314. '<!-- ----------------------------------------SAMPLE HTML END-->',
  315. '</div>',
  316. '<div style="clear:both"></div>',
  317. '',
  318. '<script src="../metadata.js"></script>',
  319. '<script src="dev-setup.js"></script>',
  320. '<script>',
  321. 'loadEditor(function() {',
  322. '/*----------------------------------------SAMPLE JS START*/',
  323. '',
  324. js,
  325. '',
  326. '/*----------------------------------------SAMPLE CSS END*/',
  327. '});',
  328. '</script>',
  329. '</body>',
  330. '</html>',
  331. ];
  332. fs.writeFileSync(path.join(__dirname, 'test/playground.generated/' + sampleId + '.html'), result.join('\n'));
  333. locations.push({
  334. path: sampleId + '.html',
  335. name: sample.chapter + ' &gt; ' + sample.name
  336. })
  337. }
  338. var index = [
  339. '<!DOCTYPE html>',
  340. '<!-- THIS IS A GENERATED FILE VIA gulp generate-test-samples -->',
  341. '<html>',
  342. '<head>',
  343. ' <base href="..">',
  344. '</head>',
  345. '<body>',
  346. '<a class="loading-opts" href="index.html">[&lt;&lt; BACK]</a><br/>',
  347. 'THIS IS A GENERATED FILE VIA gulp generate-test-samples<br/><br/>',
  348. locations.map(function(location) {
  349. return '<a class="loading-opts" href="playground.generated/' + location.path + '">' + location.name + '</a>';
  350. }).join('<br/>\n'),
  351. '<script src="../metadata.js"></script>',
  352. '<script src="dev-setup.js"></script>',
  353. '</body>',
  354. '</html>',
  355. ]
  356. fs.writeFileSync(path.join(__dirname, 'test/playground.generated/index.html'), index.join('\n'));
  357. });
  358. gulp.task('simpleserver', ['generate-test-samples'], function(cb) {
  359. httpServer.createServer({ root: '../', cache: 5 }).listen(8080);
  360. httpServer.createServer({ root: '../', cache: 5 }).listen(8088);
  361. console.log('LISTENING on 8080 and 8088');
  362. });