generate-metadata-for-builder.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. 'use strict';
  2. const CSON = require('season');
  3. const fs = require('fs-plus');
  4. const normalizePackageData = require('normalize-package-data');
  5. const path = require('path');
  6. const semver = require('semver');
  7. module.exports = function(packageJSON) {
  8. return {
  9. _atomPackages: buildBundledPackagesMetadata(packageJSON),
  10. _atomMenu: buildPlatformMenuMetadata(packageJSON),
  11. _atomKeymaps: buildPlatformKeymapsMetadata(packageJSON)
  12. }
  13. };
  14. function buildBundledPackagesMetadata(packageJSON) {
  15. const packages = {};
  16. for (let packageName of Object.keys(packageJSON.packageDependencies)) {
  17. const packagePath = path.join('node_modules', packageName);
  18. const packageMetadataPath = path.join(packagePath, 'package.json');
  19. const packageMetadata = JSON.parse(fs.readFileSync(packageMetadataPath, 'utf8'));
  20. const packageReadmePath = path.join(packagePath, 'README.md');
  21. packageMetadata.readme = fs.readFileSync(packageReadmePath, 'utf8').toString();
  22. normalizePackageData(
  23. packageMetadata,
  24. msg => {
  25. if (!msg.match(/No README data$/)) {
  26. console.warn(
  27. `Invalid package metadata. ${packageMetadata.name}: ${msg}`
  28. );
  29. }
  30. },
  31. true
  32. );
  33. if (
  34. packageMetadata.repository &&
  35. packageMetadata.repository.url &&
  36. packageMetadata.repository.type === 'git'
  37. ) {
  38. packageMetadata.repository.url = packageMetadata.repository.url.replace(
  39. /^git\+/,
  40. ''
  41. );
  42. }
  43. delete packageMetadata['_from'];
  44. delete packageMetadata['_id'];
  45. delete packageMetadata['dist'];
  46. delete packageMetadata['readmeFilename'];
  47. const packageModuleCache = packageMetadata._atomModuleCache || {};
  48. if (
  49. packageModuleCache.extensions &&
  50. packageModuleCache.extensions['.json']
  51. ) {
  52. const index = packageModuleCache.extensions['.json'].indexOf(
  53. 'package.json'
  54. );
  55. if (index !== -1) {
  56. packageModuleCache.extensions['.json'].splice(index, 1);
  57. }
  58. }
  59. const packageNewMetadata = {
  60. metadata: packageMetadata,
  61. keymaps: {},
  62. menus: {},
  63. grammarPaths: [],
  64. settings: {}
  65. };
  66. packageNewMetadata.rootDirPath = packagePath;
  67. if (packageMetadata.main) {
  68. const mainPath = require.resolve(
  69. path.resolve(packagePath, packageMetadata.main)
  70. );
  71. packageNewMetadata.main = path.relative(
  72. 'static',
  73. mainPath
  74. );
  75. // Convert backward slashes to forward slashes in order to allow package
  76. // main modules to be required from the snapshot. This is because we use
  77. // forward slashes to cache the sources in the snapshot, so we need to use
  78. // them here as well.
  79. packageNewMetadata.main = packageNewMetadata.main.replace(/\\/g, '/');
  80. }
  81. const packageKeymapsPath = path.join(packagePath, 'keymaps');
  82. if (fs.existsSync(packageKeymapsPath)) {
  83. for (let packageKeymapName of fs.readdirSync(packageKeymapsPath)) {
  84. const packageKeymapPath = path.join(
  85. packageKeymapsPath,
  86. packageKeymapName
  87. );
  88. if (
  89. packageKeymapPath.endsWith('.cson') ||
  90. packageKeymapPath.endsWith('.json')
  91. ) {
  92. packageNewMetadata.keymaps[packageKeymapPath] = CSON.readFileSync(
  93. packageKeymapPath
  94. );
  95. }
  96. }
  97. }
  98. const packageMenusPath = path.join(packagePath, 'menus');
  99. if (fs.existsSync(packageMenusPath)) {
  100. for (let packageMenuName of fs.readdirSync(packageMenusPath)) {
  101. const packageMenuPath = path.join(packageMenusPath, packageMenuName);
  102. if (
  103. packageMenuPath.endsWith('.cson') ||
  104. packageMenuPath.endsWith('.json')
  105. ) {
  106. packageNewMetadata.menus[packageMenuPath] = CSON.readFileSync(
  107. packageMenuPath
  108. );
  109. }
  110. }
  111. }
  112. const packageGrammarsPath = path.join(packagePath, 'grammars');
  113. for (let packageGrammarPath of fs.listSync(packageGrammarsPath, [
  114. 'json',
  115. 'cson'
  116. ])) {
  117. packageNewMetadata.grammarPaths.push(packageGrammarPath);
  118. }
  119. const packageSettingsPath = path.join(packagePath, 'settings');
  120. for (let packageSettingPath of fs.listSync(packageSettingsPath, [
  121. 'json',
  122. 'cson'
  123. ])) {
  124. packageNewMetadata.settings[packageSettingPath] = CSON.readFileSync(
  125. packageSettingPath
  126. );
  127. }
  128. const packageStyleSheetsPath = path.join(packagePath, 'styles');
  129. let styleSheets = null;
  130. if (packageMetadata.mainStyleSheet) {
  131. styleSheets = [fs.resolve(packagePath, packageMetadata.mainStyleSheet)];
  132. } else if (packageMetadata.styleSheets) {
  133. styleSheets = packageMetadata.styleSheets.map(name =>
  134. fs.resolve(packageStyleSheetsPath, name, ['css', 'less', ''])
  135. );
  136. } else {
  137. const indexStylesheet = fs.resolve(packagePath, 'index', ['css', 'less']);
  138. if (indexStylesheet) {
  139. styleSheets = [indexStylesheet];
  140. } else {
  141. styleSheets = fs.listSync(packageStyleSheetsPath, ['css', 'less']);
  142. }
  143. }
  144. packageNewMetadata.styleSheetPaths = styleSheets.map(styleSheetPath =>
  145. path.relative(packagePath, styleSheetPath)
  146. );
  147. packages[packageMetadata.name] = packageNewMetadata;
  148. if (packageModuleCache.extensions) {
  149. for (let extension of Object.keys(packageModuleCache.extensions)) {
  150. const paths = packageModuleCache.extensions[extension];
  151. if (paths.length === 0) {
  152. delete packageModuleCache.extensions[extension];
  153. }
  154. }
  155. }
  156. }
  157. return packages;
  158. }
  159. function buildPlatformMenuMetadata(packageJSON) {
  160. const menuPath = path.join(
  161. 'menus',
  162. `${process.platform}.cson`
  163. );
  164. if (fs.existsSync(menuPath)) {
  165. return CSON.readFileSync(menuPath);
  166. } else {
  167. return null;
  168. }
  169. }
  170. function buildPlatformKeymapsMetadata(packageJSON) {
  171. const invalidPlatforms = [
  172. 'darwin',
  173. 'freebsd',
  174. 'linux',
  175. 'sunos',
  176. 'win32'
  177. ].filter(p => p !== process.platform);
  178. const keymapsPath = 'keymaps';
  179. const keymaps = {};
  180. for (let keymapName of fs.readdirSync(keymapsPath)) {
  181. const keymapPath = path.join(keymapsPath, keymapName);
  182. if (keymapPath.endsWith('.cson') || keymapPath.endsWith('.json')) {
  183. const keymapPlatform = path.basename(
  184. keymapPath,
  185. path.extname(keymapPath)
  186. );
  187. if (invalidPlatforms.indexOf(keymapPlatform) === -1) {
  188. keymaps[path.basename(keymapPath)] = CSON.readFileSync(keymapPath);
  189. }
  190. }
  191. }
  192. return keymaps;
  193. }