website.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. //@ts-check
  6. /** @typedef {import('../build/utils').IFile} IFile */
  7. const glob = require('glob');
  8. const path = require('path');
  9. const fs = require('fs');
  10. const cp = require('child_process');
  11. const CleanCSS = require('clean-css');
  12. const { REPO_ROOT, readFiles, writeFiles } = require('./utils');
  13. const { removeDir } = require('./fs');
  14. /** @type {string} */
  15. const MONACO_EDITOR_VERSION = (() => {
  16. const output = cp.execSync(`npm show monaco-editor version`).toString();
  17. const version = output.split(/\r\n|\r|\n/g)[0];
  18. if (!/\d+\.\d+\.\d+/.test(version)) {
  19. console.log('unrecognized package.json version: ' + version);
  20. process.exit(1);
  21. }
  22. return version;
  23. })();
  24. removeDir(`../monaco-editor-website`);
  25. checkSamples();
  26. generateWebsite();
  27. /**
  28. * Check that there are samples for all available languages
  29. */
  30. function checkSamples() {
  31. let languages = glob
  32. .sync('src/basic-languages/*/*.contribution.ts', { cwd: REPO_ROOT })
  33. .map((f) => path.dirname(f))
  34. .map((f) => f.substring('src/basic-languages/'.length));
  35. languages.push('css');
  36. languages.push('html');
  37. languages.push('json');
  38. languages.push('typescript');
  39. // some languages have a different id than their folder
  40. languages = languages.map((l) => {
  41. switch (l) {
  42. case 'coffee':
  43. return 'coffeescript';
  44. case 'protobuf':
  45. return 'proto';
  46. case 'solidity':
  47. return 'sol';
  48. case 'sophia':
  49. return 'aes';
  50. default:
  51. return l;
  52. }
  53. });
  54. let fail = false;
  55. for (const language of languages) {
  56. const expectedSamplePath = path.join(REPO_ROOT, `website/index/samples/sample.${language}.txt`);
  57. if (!fs.existsSync(expectedSamplePath)) {
  58. console.error(`Missing sample for ${language} at ${expectedSamplePath}`);
  59. fail = true;
  60. }
  61. }
  62. if (fail) {
  63. process.exit(1);
  64. }
  65. }
  66. /**
  67. * @param {string} dataPath
  68. * @param {string} contents
  69. * @param {RegExp} regex
  70. * @param {(match:string, fileContents:Buffer)=>string} callback
  71. * @returns {string}
  72. */
  73. function replaceWithRelativeResource(dataPath, contents, regex, callback) {
  74. return contents.replace(regex, function (_, m0) {
  75. const filePath = path.join(REPO_ROOT, 'website', path.dirname(dataPath), m0);
  76. return callback(m0, fs.readFileSync(filePath));
  77. });
  78. }
  79. function generateWebsite() {
  80. const files = readFiles('website/**/*', {
  81. base: 'website',
  82. ignore: ['website/typedoc/**/*'],
  83. dot: true
  84. });
  85. for (const file of files) {
  86. if (!file.contents || !/\.(html)$/.test(file.path) || /new-samples/.test(file.path)) {
  87. continue;
  88. }
  89. let contents = file.contents.toString();
  90. contents = contents.replace(/\.\.\/release\/dev/g, 'node_modules/monaco-editor/min');
  91. // contents = contents.replace(/\.\.\/\.\.\/release\/dev/g, '../monaco-editor/release/dev');
  92. contents = contents.replace(/{{version}}/g, MONACO_EDITOR_VERSION);
  93. contents = contents.replace(/{{year}}/g, String(new Date().getFullYear()));
  94. // Preload xhr contents
  95. contents = replaceWithRelativeResource(
  96. file.path,
  97. contents,
  98. /<pre data-preload="([^"]+)".*/g,
  99. function (m0, fileContents) {
  100. return (
  101. '<pre data-preload="' +
  102. m0 +
  103. '" style="display:none">' +
  104. fileContents
  105. .toString('utf8')
  106. .replace(/&/g, '&amp;')
  107. .replace(/</g, '&lt;')
  108. .replace(/>/g, '&gt;') +
  109. '</pre>'
  110. );
  111. }
  112. );
  113. // Inline fork.png
  114. contents = replaceWithRelativeResource(
  115. file.path,
  116. contents,
  117. /src="(\.\/fork.png)"/g,
  118. function (m0, fileContents) {
  119. return 'src="data:image/png;base64,' + fileContents.toString('base64') + '"';
  120. }
  121. );
  122. // let allCSS = '';
  123. contents = replaceWithRelativeResource(
  124. file.path,
  125. contents,
  126. /<link data-inline="yes-please" href="([^"]+)".*/g,
  127. function (m0, fileContents) {
  128. const minifiedCSS = new CleanCSS().minify(fileContents.toString('utf8')).styles;
  129. return `<style>${minifiedCSS}</style>`;
  130. }
  131. );
  132. // Inline javascript
  133. contents = replaceWithRelativeResource(
  134. file.path,
  135. contents,
  136. /<script data-inline="yes-please" src="([^"]+)".*/g,
  137. function (m0, fileContents) {
  138. return '<script>' + fileContents.toString('utf8') + '</script>';
  139. }
  140. );
  141. file.contents = Buffer.from(contents.split(/\r\n|\r|\n/).join('\n'));
  142. }
  143. writeFiles(files, `../monaco-editor-website`);
  144. // temporarily create package.json so that npm install doesn't bark
  145. fs.writeFileSync(path.join(REPO_ROOT, '../monaco-editor-website/package.json'), '{}');
  146. fs.writeFileSync(path.join(REPO_ROOT, '../monaco-editor-website/.nojekyll'), '');
  147. cp.execSync('npm install monaco-editor', {
  148. cwd: path.join(REPO_ROOT, '../monaco-editor-website')
  149. });
  150. fs.unlinkSync(path.join(REPO_ROOT, '../monaco-editor-website/package.json'));
  151. }