Files
atom/script/lib/generate-metadata.js
2019-06-01 00:29:10 +02:00

292 lines
8.8 KiB
JavaScript

'use strict';
const CSON = require('season');
const deprecatedPackagesMetadata = require('../deprecated-packages');
const fs = require('fs-plus');
const normalizePackageData = require('normalize-package-data');
const path = require('path');
const semver = require('semver');
const CONFIG = require('../config');
let appName = CONFIG.appMetadata.name;
if (process.platform === 'win32') {
// Use the channel name in the app name on Windows so that the installer will
// place it in a different folder in AppData\Local
appName = CONFIG.channel === 'stable' ? 'atom' : `atom-${CONFIG.channel}`;
}
module.exports = function() {
console.log(
`Generating metadata for ${path.join(
CONFIG.intermediateAppPath,
'package.json'
)}`
);
CONFIG.appMetadata._atomPackages = buildBundledPackagesMetadata();
CONFIG.appMetadata._atomMenu = buildPlatformMenuMetadata();
CONFIG.appMetadata._atomKeymaps = buildPlatformKeymapsMetadata();
CONFIG.appMetadata._deprecatedPackages = deprecatedPackagesMetadata;
CONFIG.appMetadata.version = CONFIG.computedAppVersion;
CONFIG.appMetadata.name = appName;
CONFIG.appMetadata.productName = CONFIG.appName;
checkDeprecatedPackagesMetadata();
fs.writeFileSync(
path.join(CONFIG.intermediateAppPath, 'package.json'),
JSON.stringify(CONFIG.appMetadata)
);
};
module.exports = function() {
console.log(
`Generating metadata for ${path.join(
CONFIG.intermediateAppPath,
'package.json'
)}`
);
CONFIG.appMetadata._atomPackages = buildBundledPackagesMetadata();
CONFIG.appMetadata._atomMenu = buildPlatformMenuMetadata();
CONFIG.appMetadata._atomKeymaps = buildPlatformKeymapsMetadata();
CONFIG.appMetadata._deprecatedPackages = deprecatedPackagesMetadata;
CONFIG.appMetadata.version = CONFIG.computedAppVersion;
checkDeprecatedPackagesMetadata();
fs.writeFileSync(
path.join(CONFIG.intermediateAppPath, 'package.json'),
JSON.stringify(CONFIG.appMetadata)
);
};
function buildBundledPackagesMetadata() {
const packages = {};
for (let packageName of Object.keys(CONFIG.appMetadata.packageDependencies)) {
const packagePath = path.join(
CONFIG.intermediateAppPath,
'node_modules',
packageName
);
const packageMetadataPath = path.join(packagePath, 'package.json');
const packageMetadata = JSON.parse(
fs.readFileSync(packageMetadataPath, 'utf8')
);
normalizePackageData(
packageMetadata,
msg => {
if (!msg.match(/No README data$/)) {
console.warn(
`Invalid package metadata. ${packageMetadata.name}: ${msg}`
);
}
},
true
);
if (
packageMetadata.repository &&
packageMetadata.repository.url &&
packageMetadata.repository.type === 'git'
) {
packageMetadata.repository.url = packageMetadata.repository.url.replace(
/^git\+/,
''
);
}
delete packageMetadata['_from'];
delete packageMetadata['_id'];
delete packageMetadata['dist'];
delete packageMetadata['readme'];
delete packageMetadata['readmeFilename'];
const packageModuleCache = packageMetadata._atomModuleCache || {};
if (
packageModuleCache.extensions &&
packageModuleCache.extensions['.json']
) {
const index = packageModuleCache.extensions['.json'].indexOf(
'package.json'
);
if (index !== -1) {
packageModuleCache.extensions['.json'].splice(index, 1);
}
}
const packageNewMetadata = {
metadata: packageMetadata,
keymaps: {},
menus: {},
grammarPaths: [],
settings: {}
};
packageNewMetadata.rootDirPath = path.relative(
CONFIG.intermediateAppPath,
packagePath
);
if (packageMetadata.main) {
const mainPath = require.resolve(
path.resolve(packagePath, packageMetadata.main)
);
packageNewMetadata.main = path.relative(
path.join(CONFIG.intermediateAppPath, 'static'),
mainPath
);
// Convert backward slashes to forward slashes in order to allow package
// main modules to be required from the snapshot. This is because we use
// forward slashes to cache the sources in the snapshot, so we need to use
// them here as well.
packageNewMetadata.main = packageNewMetadata.main.replace(/\\/g, '/');
}
const packageKeymapsPath = path.join(packagePath, 'keymaps');
if (fs.existsSync(packageKeymapsPath)) {
for (let packageKeymapName of fs.readdirSync(packageKeymapsPath)) {
const packageKeymapPath = path.join(
packageKeymapsPath,
packageKeymapName
);
if (
packageKeymapPath.endsWith('.cson') ||
packageKeymapPath.endsWith('.json')
) {
const relativePath = path.relative(
CONFIG.intermediateAppPath,
packageKeymapPath
);
packageNewMetadata.keymaps[relativePath] = CSON.readFileSync(
packageKeymapPath
);
}
}
}
const packageMenusPath = path.join(packagePath, 'menus');
if (fs.existsSync(packageMenusPath)) {
for (let packageMenuName of fs.readdirSync(packageMenusPath)) {
const packageMenuPath = path.join(packageMenusPath, packageMenuName);
if (
packageMenuPath.endsWith('.cson') ||
packageMenuPath.endsWith('.json')
) {
const relativePath = path.relative(
CONFIG.intermediateAppPath,
packageMenuPath
);
packageNewMetadata.menus[relativePath] = CSON.readFileSync(
packageMenuPath
);
}
}
}
const packageGrammarsPath = path.join(packagePath, 'grammars');
for (let packageGrammarPath of fs.listSync(packageGrammarsPath, [
'json',
'cson'
])) {
const relativePath = path.relative(
CONFIG.intermediateAppPath,
packageGrammarPath
);
packageNewMetadata.grammarPaths.push(relativePath);
}
const packageSettingsPath = path.join(packagePath, 'settings');
for (let packageSettingPath of fs.listSync(packageSettingsPath, [
'json',
'cson'
])) {
const relativePath = path.relative(
CONFIG.intermediateAppPath,
packageSettingPath
);
packageNewMetadata.settings[relativePath] = CSON.readFileSync(
packageSettingPath
);
}
const packageStyleSheetsPath = path.join(packagePath, 'styles');
let styleSheets = null;
if (packageMetadata.mainStyleSheet) {
styleSheets = [fs.resolve(packagePath, packageMetadata.mainStyleSheet)];
} else if (packageMetadata.styleSheets) {
styleSheets = packageMetadata.styleSheets.map(name =>
fs.resolve(packageStyleSheetsPath, name, ['css', 'less', ''])
);
} else {
const indexStylesheet = fs.resolve(packagePath, 'index', ['css', 'less']);
if (indexStylesheet) {
styleSheets = [indexStylesheet];
} else {
styleSheets = fs.listSync(packageStyleSheetsPath, ['css', 'less']);
}
}
packageNewMetadata.styleSheetPaths = styleSheets.map(styleSheetPath =>
path.relative(packagePath, styleSheetPath)
);
packages[packageMetadata.name] = packageNewMetadata;
if (packageModuleCache.extensions) {
for (let extension of Object.keys(packageModuleCache.extensions)) {
const paths = packageModuleCache.extensions[extension];
if (paths.length === 0) {
delete packageModuleCache.extensions[extension];
}
}
}
}
return packages;
}
function buildPlatformMenuMetadata() {
const menuPath = path.join(
CONFIG.repositoryRootPath,
'menus',
`${process.platform}.cson`
);
if (fs.existsSync(menuPath)) {
return CSON.readFileSync(menuPath);
} else {
return null;
}
}
function buildPlatformKeymapsMetadata() {
const invalidPlatforms = [
'darwin',
'freebsd',
'linux',
'sunos',
'win32'
].filter(p => p !== process.platform);
const keymapsPath = path.join(CONFIG.repositoryRootPath, 'keymaps');
const keymaps = {};
for (let keymapName of fs.readdirSync(keymapsPath)) {
const keymapPath = path.join(keymapsPath, keymapName);
if (keymapPath.endsWith('.cson') || keymapPath.endsWith('.json')) {
const keymapPlatform = path.basename(
keymapPath,
path.extname(keymapPath)
);
if (invalidPlatforms.indexOf(keymapPlatform) === -1) {
keymaps[path.basename(keymapPath)] = CSON.readFileSync(keymapPath);
}
}
}
return keymaps;
}
function checkDeprecatedPackagesMetadata() {
for (let packageName of Object.keys(deprecatedPackagesMetadata)) {
const packageMetadata = deprecatedPackagesMetadata[packageName];
if (
packageMetadata.version &&
!semver.validRange(packageMetadata.version)
) {
throw new Error(
`Invalid range: ${packageMetadata.version} (${packageName}).`
);
}
}
}