ng-packagr
Version:
Compile and package Angular libraries in Angular Package Format (APF)
203 lines • 8.44 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const esbuild_1 = require("esbuild");
const node_path_1 = require("node:path");
const node_url_1 = require("node:url");
const node_worker_threads_1 = require("node:worker_threads");
const postcss_1 = __importDefault(require("postcss"));
const cache_1 = require("../utils/cache");
const log = __importStar(require("../utils/log"));
const css_resource_plugin_1 = require("./css-resource-plugin");
const { tailwindConfigPath, projectBasePath, browserslistData, targets, cssUrl, styleIncludePaths, postcssConfiguration, } = node_worker_threads_1.workerData;
let cacheDirectory = node_worker_threads_1.workerData.cacheDirectory;
let postCssProcessor;
const CACHE_KEY_VALUES = [...browserslistData, ...styleIncludePaths, cssUrl].join(':');
/**
* An array of keywords that indicate Tailwind CSS processing is required for a stylesheet.
*
* Based on https://tailwindcss.com/docs/functions-and-directives
*/
const TAILWIND_KEYWORDS = [
'@tailwind',
'@layer',
'@apply',
'@config',
'theme(',
'screen(',
'@screen', // Undocumented in version 3, see: https://github.com/tailwindlabs/tailwindcss/discussions/7516.
];
async function render({ content, filePath }) {
let key;
if (cacheDirectory && !content.includes('@import') && !content.includes('@use')) {
// No transitive deps, we can cache more aggressively.
key = await (0, cache_1.generateKey)(content, CACHE_KEY_VALUES);
const result = await (0, cache_1.readCacheEntry)(cacheDirectory, key);
if (result) {
result.warnings.forEach(msg => log.warn(msg));
return result.css;
}
}
// Render pre-processor language (sass, styl, less)
let renderedCss = await renderCss(filePath, content);
// We cannot cache CSS re-rendering phase, because a transitive dependency via (@import) can case different CSS output.
// Example a change in a mixin or SCSS variable.
if (!key) {
key = await (0, cache_1.generateKey)(renderedCss, CACHE_KEY_VALUES);
}
if (cacheDirectory) {
const cachedResult = await (0, cache_1.readCacheEntry)(cacheDirectory, key);
if (cachedResult) {
cachedResult.warnings.forEach(msg => log.warn(msg));
return cachedResult.css;
}
}
const warnings = [];
if (postCssProcessor && (postcssConfiguration || (tailwindConfigPath && hasTailwindKeywords(renderedCss)))) {
const result = await postCssProcessor.process(renderedCss, {
from: filePath,
to: filePath.replace((0, node_path_1.extname)(filePath), '.css'),
});
warnings.push(...result.warnings().map(w => w.toString()));
renderedCss = result.css;
}
const { outputFiles, warnings: esBuildWarnings, errors: esbuildErrors, } = await (0, esbuild_1.build)({
stdin: {
contents: renderedCss,
loader: 'css',
resolveDir: (0, node_path_1.dirname)(filePath),
},
plugins: [(0, css_resource_plugin_1.createCssResourcePlugin)(cssUrl)],
write: false,
sourcemap: false,
minify: true,
bundle: true,
absWorkingDir: projectBasePath,
target: targets,
});
const code = outputFiles[0].text;
if (esBuildWarnings.length > 0) {
warnings.push(...(await (0, esbuild_1.formatMessages)(esBuildWarnings, { kind: 'warning' })));
warnings.forEach(msg => log.warn(msg));
}
if (esbuildErrors.length > 0) {
const errors = await (0, esbuild_1.formatMessages)(esBuildWarnings, { kind: 'error' });
errors.forEach(msg => log.error(msg));
throw new Error(`An error has occuried while processing ${filePath}.`);
}
if (cacheDirectory) {
await (0, cache_1.saveCacheEntry)(cacheDirectory, key, JSON.stringify({
css: code,
warnings,
}));
}
return code;
}
async function renderCss(filePath, css) {
const ext = (0, node_path_1.extname)(filePath);
switch (ext) {
case '.sass':
case '.scss': {
return (await Promise.resolve().then(() => __importStar(require('sass')))).compileString(css, {
url: (0, node_url_1.pathToFileURL)(filePath),
syntax: '.sass' === ext ? 'indented' : 'scss',
loadPaths: styleIncludePaths,
}).css;
}
case '.less': {
const { css: content } = await (await Promise.resolve().then(() => __importStar(require('less')))).default.render(css, {
filename: filePath,
javascriptEnabled: true,
paths: styleIncludePaths,
});
return content;
}
case '.css':
default:
return css;
}
}
function getTailwindPlugin() {
// Attempt to setup Tailwind CSS
// Only load Tailwind CSS plugin if configuration file was found.
// This acts as a guard to ensure the project actually wants to use Tailwind CSS.
// The package may be unknowningly present due to a third-party transitive package dependency.
if (tailwindConfigPath) {
let tailwindPackagePath;
try {
tailwindPackagePath = require.resolve('tailwindcss', { paths: [projectBasePath] });
}
catch {
const relativeTailwindConfigPath = (0, node_path_1.relative)(projectBasePath, tailwindConfigPath);
log.warn(`Tailwind CSS configuration file found (${relativeTailwindConfigPath})` +
` but the 'tailwindcss' package is not installed.` +
` To enable Tailwind CSS, please install the 'tailwindcss' package.`);
}
if (tailwindPackagePath) {
return require(tailwindPackagePath)({ config: tailwindConfigPath });
}
}
}
async function initialize() {
const postCssPlugins = [];
if (postcssConfiguration) {
for (const [pluginName, pluginOptions] of postcssConfiguration.plugins) {
const { default: plugin } = await Promise.resolve(`${pluginName}`).then(s => __importStar(require(s)));
if (typeof plugin !== 'function' || plugin.postcss !== true) {
throw new Error(`Attempted to load invalid Postcss plugin: "${pluginName}"`);
}
postCssPlugins.push(plugin(pluginOptions));
}
}
else {
const tailwinds = getTailwindPlugin();
if (tailwinds) {
postCssPlugins.push(tailwinds);
cacheDirectory = undefined;
}
}
if (postCssPlugins.length) {
postCssProcessor = (0, postcss_1.default)(postCssPlugins);
}
// Return the render function for use
return render;
}
/**
* Searches the provided contents for keywords that indicate Tailwind is used
* within a stylesheet.
*/
function hasTailwindKeywords(contents) {
// TODO: use better search algorithm for keywords
return TAILWIND_KEYWORDS.some(keyword => contents.includes(keyword));
}
/**
* The default export will be the promise returned by the initialize function.
* This is awaited by piscina prior to using the Worker.
*/
exports.default = initialize();
//# sourceMappingURL=stylesheet-processor-worker.js.map
;