pulsar/script/lib/prebuild-less-cache.js
2019-05-31 18:33:56 +02:00

219 lines
6.4 KiB
JavaScript

'use strict';
const fs = require('fs');
const klawSync = require('klaw-sync');
const glob = require('glob');
const path = require('path');
const LessCache = require('less-cache');
const CONFIG = require('../config');
const LESS_CACHE_VERSION = require('less-cache/package.json').version;
const FALLBACK_VARIABLE_IMPORTS =
'@import "variables/ui-variables";\n@import "variables/syntax-variables";\n';
module.exports = function() {
const cacheDirPath = path.join(
CONFIG.intermediateAppPath,
'less-compile-cache'
);
console.log(`Generating pre-built less cache in ${cacheDirPath}`);
// Group bundled packages into UI themes, syntax themes, and non-theme packages
const uiThemes = [];
const syntaxThemes = [];
const nonThemePackages = [];
for (let packageName in CONFIG.appMetadata.packageDependencies) {
const packageMetadata = require(path.join(
CONFIG.intermediateAppPath,
'node_modules',
packageName,
'package.json'
));
if (packageMetadata.theme === 'ui') {
uiThemes.push(packageName);
} else if (packageMetadata.theme === 'syntax') {
syntaxThemes.push(packageName);
} else {
nonThemePackages.push(packageName);
}
}
CONFIG.snapshotAuxiliaryData.lessSourcesByRelativeFilePath = {};
function saveIntoSnapshotAuxiliaryData(absoluteFilePath, content) {
const relativeFilePath = path.relative(
CONFIG.intermediateAppPath,
absoluteFilePath
);
if (
!CONFIG.snapshotAuxiliaryData.lessSourcesByRelativeFilePath.hasOwnProperty(
relativeFilePath
)
) {
CONFIG.snapshotAuxiliaryData.lessSourcesByRelativeFilePath[
relativeFilePath
] = {
content: content,
digest: LessCache.digestForContent(content)
};
}
}
CONFIG.snapshotAuxiliaryData.importedFilePathsByRelativeImportPath = {};
// Warm cache for every combination of the default UI and syntax themes,
// because themes assign variables which may be used in any style sheet.
for (let uiTheme of uiThemes) {
for (let syntaxTheme of syntaxThemes) {
// Build a LessCache instance with import paths based on the current theme combination
const lessCache = new LessCache({
cacheDir: cacheDirPath,
fallbackDir: path.join(
CONFIG.atomHomeDirPath,
'compile-cache',
'prebuild-less',
LESS_CACHE_VERSION
),
syncCaches: true,
resourcePath: CONFIG.intermediateAppPath,
importPaths: [
path.join(
CONFIG.intermediateAppPath,
'node_modules',
syntaxTheme,
'styles'
),
path.join(
CONFIG.intermediateAppPath,
'node_modules',
uiTheme,
'styles'
),
path.join(CONFIG.intermediateAppPath, 'static', 'variables'),
path.join(CONFIG.intermediateAppPath, 'static')
]
});
// Store file paths located at the import paths so that we can avoid scanning them at runtime.
for (const absoluteImportPath of lessCache.getImportPaths()) {
const relativeImportPath = path.relative(
CONFIG.intermediateAppPath,
absoluteImportPath
);
if (
!CONFIG.snapshotAuxiliaryData.importedFilePathsByRelativeImportPath.hasOwnProperty(
relativeImportPath
)
) {
CONFIG.snapshotAuxiliaryData.importedFilePathsByRelativeImportPath[
relativeImportPath
] = [];
for (const importedFile of klawSync(absoluteImportPath, {
nodir: true
})) {
CONFIG.snapshotAuxiliaryData.importedFilePathsByRelativeImportPath[
relativeImportPath
].push(
path.relative(CONFIG.intermediateAppPath, importedFile.path)
);
}
}
}
// Cache all styles in static; don't append variable imports
for (let lessFilePath of glob.sync(
path.join(CONFIG.intermediateAppPath, 'static', '**', '*.less')
)) {
cacheCompiledCSS(lessCache, lessFilePath, false);
}
// Cache styles for all bundled non-theme packages
for (let nonThemePackage of nonThemePackages) {
for (let lessFilePath of glob.sync(
path.join(
CONFIG.intermediateAppPath,
'node_modules',
nonThemePackage,
'**',
'*.less'
)
)) {
cacheCompiledCSS(lessCache, lessFilePath, true);
}
}
// Cache styles for this UI theme
const uiThemeMainPath = path.join(
CONFIG.intermediateAppPath,
'node_modules',
uiTheme,
'index.less'
);
cacheCompiledCSS(lessCache, uiThemeMainPath, true);
for (let lessFilePath of glob.sync(
path.join(
CONFIG.intermediateAppPath,
'node_modules',
uiTheme,
'**',
'*.less'
)
)) {
if (lessFilePath !== uiThemeMainPath) {
saveIntoSnapshotAuxiliaryData(
lessFilePath,
fs.readFileSync(lessFilePath, 'utf8')
);
}
}
// Cache styles for this syntax theme
const syntaxThemeMainPath = path.join(
CONFIG.intermediateAppPath,
'node_modules',
syntaxTheme,
'index.less'
);
cacheCompiledCSS(lessCache, syntaxThemeMainPath, true);
for (let lessFilePath of glob.sync(
path.join(
CONFIG.intermediateAppPath,
'node_modules',
syntaxTheme,
'**',
'*.less'
)
)) {
if (lessFilePath !== syntaxThemeMainPath) {
saveIntoSnapshotAuxiliaryData(
lessFilePath,
fs.readFileSync(lessFilePath, 'utf8')
);
}
}
}
}
for (let lessFilePath of glob.sync(
path.join(
CONFIG.intermediateAppPath,
'node_modules',
'atom-ui',
'**',
'*.less'
)
)) {
saveIntoSnapshotAuxiliaryData(
lessFilePath,
fs.readFileSync(lessFilePath, 'utf8')
);
}
function cacheCompiledCSS(lessCache, lessFilePath, importFallbackVariables) {
let lessSource = fs.readFileSync(lessFilePath, 'utf8');
if (importFallbackVariables) {
lessSource = FALLBACK_VARIABLE_IMPORTS + lessSource;
}
lessCache.cssForFile(lessFilePath, lessSource);
saveIntoSnapshotAuxiliaryData(lessFilePath, lessSource);
}
};