@morfeo/compiler
Version:

125 lines • 5.44 kB
JavaScript
import { __awaiter } from "tslib";
import * as fs from 'fs';
import * as path from 'path';
import * as chokidar from 'chokidar';
import { glob } from 'glob';
import * as babel from '@babel/core';
import morfeoBabelPlugin from '@morfeo/babel-plugin';
import { morfeo, resolveMultiThemeValue } from '@morfeo/web';
import { getStyles } from '@morfeo/jss';
import { deepMerge } from '@morfeo/utils';
import { createWriter } from './writer';
import { logger } from './logger';
const DEFAULT_BABEL_PRESETS = ['@babel/preset-env', '@babel/preset-typescript'];
const DEFAULT_BABEL_PLUGINS = ['@babel/plugin-syntax-jsx'];
const DEFAULT_OPTIONS = {
emojis: false,
classNamePrefix: '',
entryPoints: [path.join('.', '**/*.{ts,tsx,js,jsx}')],
output: path.join(__dirname, '..', 'css', 'morfeo.css'),
theme: {},
watch: false,
};
function createCollector() {
const cache = new Map();
let options = DEFAULT_OPTIONS;
let writer = createWriter({
output: DEFAULT_OPTIONS.output,
});
function init(pluginOptions) {
var _a, _b, _c, _d;
options = Object.assign(Object.assign(Object.assign({}, DEFAULT_OPTIONS), pluginOptions), { babel: Object.assign(Object.assign({}, pluginOptions.babel), { presets: Array.from(new Set([
...DEFAULT_BABEL_PRESETS,
...(((_a = options.babel) === null || _a === void 0 ? void 0 : _a.presets) || []),
...(((_b = pluginOptions.babel) === null || _b === void 0 ? void 0 : _b.presets) || []),
])), plugins: Array.from(new Set([
...DEFAULT_BABEL_PLUGINS,
...(((_c = options.babel) === null || _c === void 0 ? void 0 : _c.plugins) || []),
...(((_d = pluginOptions.babel) === null || _d === void 0 ? void 0 : _d.plugins) || []),
[morfeoBabelPlugin, {}],
])) }) });
morfeo.theme.set(options.theme);
writer = createWriter({
delay: 10,
output: pluginOptions.output || DEFAULT_OPTIONS.output,
});
}
function write() {
return __awaiter(this, void 0, void 0, function* () {
function onWrite() {
const { light = {}, dark = {} } = morfeo.theme.getMetadata();
const variables = getStyles({
'@global': {
':root': light,
[resolveMultiThemeValue('dark')]: {
':root': dark,
},
},
}).sheet.toString();
const mergedCss = Array.from(cache.entries()).reduce((acc, [, { globalStyles, styles }]) => {
return {
globalStyles: deepMerge(acc.globalStyles, globalStyles),
styles: deepMerge(acc.styles, styles),
};
}, { globalStyles: {}, styles: {} });
const css = [
...Object.values(mergedCss.globalStyles),
...Object.values(mergedCss.styles),
].join('\n');
return `${variables}\n${css}`;
}
return writer(onWrite);
});
}
function extract(fileName) {
return __awaiter(this, void 0, void 0, function* () {
const fileContent = fs.readFileSync(fileName, { encoding: 'utf-8' });
const result = yield babel.transformAsync(fileContent, Object.assign(Object.assign({}, options.babel), { sourceFileName: fileName, filename: path.basename(fileName), sourceMaps: false, code: false, ast: false }));
// @ts-ignore
if (!result || !result.metadata || !result.metadata.morfeo) {
return { globalStyles: {}, styles: {} };
}
// @ts-ignore
return result.metadata.morfeo;
});
}
function collectFile(fileName) {
return __awaiter(this, void 0, void 0, function* () {
const css = yield extract(fileName);
cache.set(fileName, css);
write();
});
}
function watch(entryPoints) {
const watcher = chokidar.watch(entryPoints, {
ignoreInitial: true,
});
watcher.add(entryPoints).on('add', fileName => {
logger.debug(`${path.basename(fileName)} added`);
collectFile(fileName);
});
watcher.add(entryPoints).on('change', fileName => {
logger.debug(`${path.basename(fileName)} changed`);
collectFile(fileName);
});
}
function collect() {
return __awaiter(this, void 0, void 0, function* () {
const entryPoints = options.entryPoints || DEFAULT_OPTIONS.entryPoints;
logger.debug(`Start extracting CSS from ${entryPoints}`);
const fileNames = yield glob(entryPoints);
logger.startTimer('css extraction');
Promise.all(fileNames.map(collectFile)).then(() => {
const diff = logger.endTimer('css extraction');
logger.debug(`CSS extracted in ${diff} seconds.`);
});
if (options.watch) {
logger.debug('Watching for file changes');
watch(entryPoints);
}
});
}
return { init, collect };
}
export const collector = createCollector();
//# sourceMappingURL=collector.js.map